diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-07-05 14:31:07 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-07-05 14:31:07 -0300 |
commit | 30982bec968fd34694b5be3ecbbc92de78d8eacb (patch) | |
tree | 9b2b350be7c79b7237e8ffbe84dc90c6c7cc5089 | |
parent | 1ab3208a1fceb12fca8f24ba57d6e13c5bff15e3 (diff) | |
download | lua-30982bec968fd34694b5be3ecbbc92de78d8eacb.tar.gz lua-30982bec968fd34694b5be3ecbbc92de78d8eacb.tar.bz2 lua-30982bec968fd34694b5be3ecbbc92de78d8eacb.zip |
Bug: Bad stack manipulation in 'multiline' (REPL)
'incomplete' was popping error message that should be used in case
there is no more lines to complete the input, that is, 'pushline'
returns NULL, due to end of file.
-rw-r--r-- | lua.c | 11 | ||||
-rw-r--r-- | testes/main.lua | 5 |
2 files changed, 10 insertions, 6 deletions
@@ -490,10 +490,8 @@ static int incomplete (lua_State *L, int status) { | |||
490 | if (status == LUA_ERRSYNTAX) { | 490 | if (status == LUA_ERRSYNTAX) { |
491 | size_t lmsg; | 491 | size_t lmsg; |
492 | const char *msg = lua_tolstring(L, -1, &lmsg); | 492 | const char *msg = lua_tolstring(L, -1, &lmsg); |
493 | if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { | 493 | if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) |
494 | lua_pop(L, 1); | ||
495 | return 1; | 494 | return 1; |
496 | } | ||
497 | } | 495 | } |
498 | return 0; /* else... */ | 496 | return 0; /* else... */ |
499 | } | 497 | } |
@@ -508,9 +506,9 @@ static int pushline (lua_State *L, int firstline) { | |||
508 | size_t l; | 506 | size_t l; |
509 | const char *prmt = get_prompt(L, firstline); | 507 | const char *prmt = get_prompt(L, firstline); |
510 | int readstatus = lua_readline(L, b, prmt); | 508 | int readstatus = lua_readline(L, b, prmt); |
511 | if (readstatus == 0) | ||
512 | return 0; /* no input (prompt will be popped by caller) */ | ||
513 | lua_pop(L, 1); /* remove prompt */ | 509 | lua_pop(L, 1); /* remove prompt */ |
510 | if (readstatus == 0) | ||
511 | return 0; /* no input */ | ||
514 | l = strlen(b); | 512 | l = strlen(b); |
515 | if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ | 513 | if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ |
516 | b[--l] = '\0'; /* remove it */ | 514 | b[--l] = '\0'; /* remove it */ |
@@ -552,8 +550,9 @@ static int multiline (lua_State *L) { | |||
552 | int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */ | 550 | int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */ |
553 | if (!incomplete(L, status) || !pushline(L, 0)) { | 551 | if (!incomplete(L, status) || !pushline(L, 0)) { |
554 | lua_saveline(L, line); /* keep history */ | 552 | lua_saveline(L, line); /* keep history */ |
555 | return status; /* cannot or should not try to add continuation line */ | 553 | return status; /* should not or cannot try to add continuation line */ |
556 | } | 554 | } |
555 | lua_remove(L, -2); /* remove error message (from incomplete line) */ | ||
557 | lua_pushliteral(L, "\n"); /* add newline... */ | 556 | lua_pushliteral(L, "\n"); /* add newline... */ |
558 | lua_insert(L, -2); /* ...between the two lines */ | 557 | lua_insert(L, -2); /* ...between the two lines */ |
559 | lua_concat(L, 3); /* join them */ | 558 | lua_concat(L, 3); /* join them */ |
diff --git a/testes/main.lua b/testes/main.lua index 11b14b44..cec4fa04 100644 --- a/testes/main.lua +++ b/testes/main.lua | |||
@@ -349,6 +349,11 @@ prepfile("a = [[b\nc\nd\ne]]\n=a") | |||
349 | RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out) | 349 | RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out) |
350 | checkprogout("b\nc\nd\ne\n\n") | 350 | checkprogout("b\nc\nd\ne\n\n") |
351 | 351 | ||
352 | -- input interrupted in continuation line | ||
353 | prepfile("a.\n") | ||
354 | RUN([[lua -i < %s > /dev/null 2> %s]], prog, out) | ||
355 | checkprogout("near <eof>\n") | ||
356 | |||
352 | local prompt = "alo" | 357 | local prompt = "alo" |
353 | prepfile[[ -- | 358 | prepfile[[ -- |
354 | a = 2 | 359 | a = 2 |