1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

vi: Do not attempt 0 or ^ commands from start of line (#524)

In vi mode, using 0 or ^ without moving from the start of the line
places cur_virt in position 0, which is left with a value of NULL.
This causes at least two bugs:

* Entering append mode results in the cursor moving in reverse,
  often with corrupted output.

* The /dev/fd/3 completion (named FIFO on FreeBSD) is reached with
  = and * completion.

Because it is unnecessary to use either 0 or ^ at the start of the
line (whether reached by ESC or otherwise), check that cur_virt is
greater than 0 and abort if the move would be ineffective.

src/cmd/ksh93/edit/vi.c:

- cntlmode(): Remove redundant '0' command handling; this caused
  the '0' command handling in mvcursor() to never be reached. It
  looks like this extra code was a workaround for a bug in ancient
  versions of ksh[*], but since at least 1995, getcount()
  special-cases an initial '0' and will not handle it as a repeat
  count parameter, which made this extra handling unnecessary.
  [*] https://github.com/ksh93/ksh/pull/524#issuecomment-1227374726

- mvcursor(): For the '0' and '^' commands, fix the bug by returning
  ABORT if the cursor position (cur_virt) is 0 or INVALID.

Related: https://github.com/ksh93/ksh/issues/520
Co-authored-by: Martijn Dekker <martijn@inlv.org>
This commit is contained in:
pghvlaans 2022-08-26 00:16:34 +09:00 committed by Martijn Dekker
parent a874586fdc
commit 58233b4c50

View file

@ -741,13 +741,8 @@ static int cntlmode(Vi_t *vp)
{
vp->repeat_set = 0;
was_inmacro = inmacro;
if( c == '0' )
{
/*** move to leftmost column ***/
cur_virt = 0;
sync_cursor(vp);
continue;
}
/*** see if it's a repeat count parameter ***/
if( digit(c) )
{
@ -1627,10 +1622,14 @@ static int mvcursor(register Vi_t* vp,register int motion)
/***** Cursor move commands *****/
case '0': /** First column **/
if(cur_virt <= 0)
return(ABORT);
tcur_virt = 0;
break;
case '^': /** First nonblank character **/
if(cur_virt <= 0)
return(ABORT);
tcur_virt = first_virt;
while( tcur_virt < last_virt && isblank(tcur_virt) )
++tcur_virt;