From 58233b4c5067511f32ddef9ee46a5ab9745e8219 Mon Sep 17 00:00:00 2001 From: pghvlaans Date: Fri, 26 Aug 2022 00:16:34 +0900 Subject: [PATCH] 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 --- src/cmd/ksh93/edit/vi.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/cmd/ksh93/edit/vi.c b/src/cmd/ksh93/edit/vi.c index d491b084b..424a82385 100644 --- a/src/cmd/ksh93/edit/vi.c +++ b/src/cmd/ksh93/edit/vi.c @@ -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;