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

emacs/vi: Fix <Tab> behaviour after command substitution

Tab completion in emacs and vi wrongly parses and executes command
substitutions. Example reproducers:

  $ $(~)<Tab>		# Result:
  $ $(~)ksh[1]: /home/johno: cannot execute [Is a directory]

  $ $(~ksh)<Tab>	# Result:
  $ $(~ksh)ksh: /home/johno/GitRepos/KornShell/ksh: cannot execute [Is a directory]

  $ $(echo true)<Tab>	# Result:
  $ /usr/bin/true	# or just 'true' -- it's unpredictable

In addition, backtick command substitutions had the following bug:

  $ `echo hi`<Tab>	# Result:
  $ `echo hi`ksh: line 1: BUG_BRACQUOT_test.sh: not found

(where BUG_BRACQUOT_test.sh happens to be lexically the
first-listed file in my ksh development working directory).

There's also a crash associated with this due to an access beyond
buffer boundaries, which is only triggered on some systems (macOS
included).

src/cmd/ksh93/edit/completion.c:
- find_begin():
  * When finding the beginning of a command substitution and the
    last character is ')', do not increase the character pointer
    cp. Increasing it caused the condition 'if(c && c==endchar)' in
    the 'default:' block to be true, causing 'return(xp);' to be
    executed, which returns a pointer the beginning of the command
    substitution to ed_expand() on line 290, so that ed_expand()
    eventually executes the command substitution with the
    sh_argbuild() call on line 349. After deleting this 'else
    cp++', that statement 'if(c && c==endchar) return(xp);' is not
    executed and `find_begin()` returns the null pointer, which
    avoids anything being executed. Thanks to @JohnoKing:
    https://github.com/ksh93/ksh/issues/268#issuecomment-817249164
  * Add code for properly skipping over backtick-style command
    substitutions, based on the $( ) code.
- ed_expand(): Avoid out[-1] reading one byte to the left of
  outbuff by first checking that out>outbuff. Thanks to @JohnoKing
  for using ASan to find the location of the crash:
  https://github.com/ksh93/ksh/issues/268#issuecomment-825574885

src/cmd/ksh93/tests/pty.sh:
- Test for the bugs detailed above.

Resolves: https://github.com/ksh93/ksh/issues/268
This commit is contained in:
Martijn Dekker 2021-05-03 18:27:44 +01:00
parent 33269cae61
commit 7a2d3564b6
2 changed files with 24 additions and 4 deletions

View file

@ -173,10 +173,16 @@ static char *find_begin(char outbuff[], char *last, int endchar, int *type)
xp = find_begin(cp,last,')',type);
if(*(cp=xp)!=')')
bp = xp;
else
cp++;
}
break;
case '`':
if(inquote=='\'')
break;
*type = mode;
xp = find_begin(cp,last,'`',type);
if(*(cp=xp)!='`')
bp = xp;
break;
case '=':
if(!inquote)
{
@ -447,9 +453,9 @@ int ed_expand(Edit_t *ep, char outbuff[],int *cur,int *eol,int mode, int count)
out = overlaid(begin,*com++,nocase);
}
mode = (out==saveout);
if(out[-1]==0)
if(out>outbuff && out[-1]==0)
out--;
if(mode && out[-1]!='/')
if(mode && (out==outbuff || out>outbuff && out[-1]!='/'))
{
if(cmd_completion)
{

View file

@ -858,5 +858,19 @@ w test \$\{.sh.level\t
r ^:test-1: test \$\{.sh.level\}\r\n$
!
# err_exit #
((SHOPT_VSH || SHOPT_ESH)) && tst $LINENO <<"!"
L tab completion executes command substitutions
# https://github.com/ksh93/ksh/issues/268
d 15
p :test-1:
w $(echo true)\t
r ^:test-1: \$\(echo true\)\r\n$
p :test-2:
w `echo true`\t
r ^:test-2: `echo true`\r\n$
!
# ======
exit $((Errors<125?Errors:125))