diff --git a/tests/sh.test b/tests/sh.test index 9f7a762c..d13acd83 100644 --- a/tests/sh.test +++ b/tests/sh.test @@ -45,6 +45,7 @@ testing "trailing \\ in ''" "$SH -c \$'echo \\'one\\\\\\ntwo\\''" \ testing 'trailing \ in ""' "$SH -c \$'echo \"one\\\\\\ntwo\"'" 'onetwo\n' \ '' '' testing 'vanishing \' "$SH -c \$'echo \\\\\\n a'" 'a\n' '' '' +testing 'command\ arg' "$SH -c \$'echo\\\\\\n abc'" 'abc\n' '' '' testing "exec3" '$C -c "{ exec readlink /proc/self/fd/0;} < /proc/self/exe"' \ "$(readlink -f $C)\n" "" "" testing 'arg shift' "$SH -c '"'for i in "" 2 1 1 1; do echo $? $1; shift $i; done'"' one two three four five" \ @@ -237,7 +238,7 @@ testing 'hidden wildcards' \ testing "backtick1" 'x=fred; echo `echo $x`' 'fred\n' "" "" testing "backtick2" 'x=fred; echo `x=y; echo $x`; echo $x' 'y\nfred\n' "" "" testing '$(( ) )' 'echo ab$((echo hello) | tr e x)cd' "abhxllocd\n" "" "" -((++SKIP)); testing '$((x=y)) lifetime' 'a=boing; echo $a $a$((a=4))$a $a' 'boing boing44 4\n' '' '' +testing '$((x=y)) lifetime' 'a=boing; echo $a $a$((a=4))$a $a' 'boing boing44 4\n' '' '' testing 'quote' "echo \"'\"" "'\n" "" "" diff --git a/toys/pending/sh.c b/toys/pending/sh.c index 2f1a510e..1dd1e0fd 100644 --- a/toys/pending/sh.c +++ b/toys/pending/sh.c @@ -1132,7 +1132,7 @@ static char *parse_word(char *start, int early) } else if (*end=='(' && strchr("?*+@!", ii)) toybuf[quote++] = ')'; else { if (ii!='\\') end--; - else if (!end[*end=='\n']) return *end ? 0 : end; + else if (!end[*end=='\n']) return (*end && !early) ? 0 : end; if (early && !quote) return end; } end++; @@ -1884,6 +1884,7 @@ static int expand_arg_nobrace(struct sh_arg *arg, char *str, unsigned flags, if (*ss != '<') ss = 0; else { while (isspace(*++ss)); + // Can't return NULL because guaranteed ) context end if (!(ll = parse_word(ss, 0)-ss)) ss = 0; else { jj = ll+(ss-s); @@ -2297,7 +2298,7 @@ static int expand_arg(struct sh_arg *arg, char *old, unsigned flags, // collect brace spans if ((TT.options&OPT_B) && !(flags&NO_BRACE)) for (i = 0; ; i++) { // skip quoted/escaped text - while ((s = parse_word(old+i, 1)) != old+i && s) i += s-(old+i); + while ((s = parse_word(old+i, 1)) != old+i) i += s-(old+i); // start a new span if (old[i] == '{') {