From 97b5ea16cff82cfab073cd89bbe038bdcd29f348 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 23 Nov 2024 02:53:29 -0600 Subject: [PATCH] Fix backslash parsing in $'' so \' doesn't end quote context. --- tests/sh.test | 7 +++++-- toys/pending/sh.c | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/sh.test b/tests/sh.test index b301e0edf..27555c7ad 100644 --- a/tests/sh.test +++ b/tests/sh.test @@ -723,9 +723,12 @@ testing '[[1<2]] is alphabetical, not numeric' '[[ 123 < 19 ]] && echo yes' \ 'yes\n' '' '' testing '[[~]]' '[[ ~ == $HOME ]] && echo yes' 'yes\n' '' '' -$BROKEN testing 'quoting contexts nest' \ - $'echo -n "$(echo "hello $(eval $\'echo -\\\\\\ne \\\'world\\n \\\'\')")"' \ +# The trailing space is because the \n gets stripped off otherwise +testing 'quoting contexts nest' \ + $'echo -n "$(echo "hello $(eval $\'echo -\\\\\\ne \\\'world\\n \\\'\')")"' \ 'hello world\n ' '' '' +testing "\$'' suppresses variable expansion" \ + $'echo $\'$(abc\'' '$(abc\n' '' '' testing 'if; is a syntax error but if $EMPTY; is not' \ 'if $NONE; then echo hello; fi' 'hello\n' '' '' diff --git a/toys/pending/sh.c b/toys/pending/sh.c index c81056e50..1be952d07 100644 --- a/toys/pending/sh.c +++ b/toys/pending/sh.c @@ -1128,7 +1128,7 @@ static char *parse_word(char *start, int early) else if (qq==254) return start+1; else if (qq==255) toybuf[quote-1] = ')'; } else if (ii==')') quote--; - } else if (ii==qq) quote--; // matching end quote + } else if (ii==(qq&127)) quote--; // matching end quote else if (qq!='\'') end--, ii = 0; // single quote claims everything if (ii) continue; // fall through for other quote types @@ -1146,11 +1146,11 @@ static char *parse_word(char *start, int early) // \? $() ${} $[] ?() *() +() @() !() else { - if (ii=='$' && -1!=(qq = stridx("({[", *end))) { + if (ii=='$' && qq != 0247 && -1!=(qq = stridx("({['", *end))) { if (strstart(&end, "((")) { end--; toybuf[quote++] = 255; - } else toybuf[quote++] = ")}]"[qq]; + } else toybuf[quote++] = ")}]\247"[qq]; // last is '+128 } else if (*end=='(' && strchr("?*+@!", ii)) toybuf[quote++] = ')'; else { if (ii!='\\') end--;