Interactively, sh_error() doesn't terminate, so echo "|$(printf %10000s)echo bug" | sh -i would read the first 8KiB, see that it's invalid, then jump back to the parser, which would then read and execute the rest of the line as-if it were the next line. The fix for this is to explicitly consume the rest of the invalid line, so that the next line observed is /actually/ the next line. This is difficult to trigger accidentally right now, since we consume the entire icanon line buffer at once (provided it's <8k, which it ~always is interactively), so we always observe one line at a time, but the next patch would make even "| echo bug" blow up. Imported-from: https://github.com/hvdijk/gwsh/commit/d279523041c1c380d64b6dec7760feba20bbf6b5 --- src/parser.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/parser.c b/src/parser.c index 8a06b9e..35fdbc3 100644 --- a/src/parser.c +++ b/src/parser.c @@ -761,6 +761,13 @@ static void nlnoprompt(void) needprompt = doprompt; } +static void +skipline(void) +{ + int c; + while ((c = pgetc()) != '\n' && c != PEOF); +} + /* * Read the next input token. @@ -798,7 +805,7 @@ xxreadtoken(void) case ' ': case '\t': continue; case '#': - while ((c = pgetc()) != '\n' && c != PEOF); + skipline(); pungetc(); continue; case '\n': @@ -1526,6 +1533,12 @@ STATIC void synerror(const char *msg) { errlinno = plinno; + + /* If we see a syntax error in a command, read the rest of the + * line now before reporting the error. This ensures we get error + * reporting that does not depend on buffering details. */ + skipline(); + sh_error("Syntax error: %s", msg); /* NOTREACHED */ } -- 2.30.2