Fix another case found by Eric Roshan-Eisner's fuzzing.
diff --git a/tests/sh.test b/tests/sh.test
index 45444d3..0cc16b9 100644
--- a/tests/sh.test
+++ b/tests/sh.test
@@ -79,6 +79,8 @@
testing '(subshell)' '$SH -c "(echo hello)"' 'hello\n' '' ''
testing 'syntax' '$SH -c "if true; then echo hello | fi" 2>/dev/null || echo x'\
'x\n' '' ''
+testing 'syntax2' '$SH -c "for;i 0" 2>&1 | { grep -qi syntax && echo yes; }' \
+ 'yes\n' '' ''
# The bash man page is lying when it says $_ starts with an absolute path.
ln -s "$(which $SH)" bash
diff --git a/toys/pending/sh.c b/toys/pending/sh.c
index 7fdec3d..6090d27 100644
--- a/toys/pending/sh.c
+++ b/toys/pending/sh.c
@@ -3176,6 +3176,9 @@
} else if (strchr(";|&", *s) && strncmp(s, "&>", 2)) {
arg->c--;
+ // Connecting nonexistent statements is an error
+ if (!arg->c || !smemcmp(ex, "do\0A", 4)) goto flush;
+
// treat ; as newline so we don't have to check both elsewhere.
if (!strcmp(s, ";")) {
arg->v[arg->c] = 0;
@@ -3186,16 +3189,12 @@
// ;; and friends only allowed in case statements
} else if (*s == ';') goto flush;
-
- // Connecting nonexistent statements is an error
- if (!arg->c) goto flush;
pl->count = -1;
continue;
// a for/select must have at least one additional argument on same line
} else if (ex && !smemcmp(ex, "do\0A", 4)) {
-
// Sanity check and break the segment
if (strncmp(s, "((", 2) && *varend(s)) goto flush;
pl->count = -1;