forked from LuaJIT/LuaJIT
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reported by Peter Cawley. (cherry-picked from commit d2f6c55) After the previous patch, it is possible to trigger the `stack overflow` error prematurely. Consider the following situation: there are already 33000 slots allocated on a Lua stack, and then there are 30 additional slots needed. In this case, the actual allocated amount would be twice the already allocated size, shrunk to the `LJ_STACK_MAXEX` size, which would lead to the stack overflow error, despite the fact there is plenty of unused space. This patch completely reworks the logic of error handling during stack growth to address the issue. Another important thing to notice is that the `LJ_ERR_STKOV` is thrown only if the `L->status` is `LUA_OK` and that status is set to `LUA_ERRRUN` just before throwing the error. The status is set to `LUA_ERRRUN` to avoid the second stack overflow during the `err_msgv` execution. Maxim Kokryashkin: * added the description and the test for the problem Part of tarantool/tarantool#9145
- Loading branch information
1 parent
f93470f
commit daa9a80
Showing
2 changed files
with
74 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
test/tarantool-c-tests/lj-962-premature-stack-overflow.test.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
#include "lua.h" | ||
#include "lauxlib.h" | ||
|
||
#include "test.h" | ||
#include "utils.h" | ||
|
||
/* | ||
* XXX: The "lj_obj.h" header is included to calculate the | ||
* number of stack slots used from the bottom of the stack. | ||
*/ | ||
#include "lj_obj.h" | ||
|
||
static int cur_slots = -1; | ||
|
||
static int fill_stack(lua_State *L) | ||
{ | ||
cur_slots = L->base - tvref(L->stack); | ||
|
||
while(lua_gettop(L) < LUAI_MAXSTACK) { | ||
cur_slots += 1; | ||
lua_pushinteger(L, 42); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int premature_stackoverflow(void *test_state) | ||
{ | ||
lua_State *L = test_state; | ||
lua_cpcall(L, fill_stack, NULL); | ||
assert_true(cur_slots == LUAI_MAXSTACK - 1); | ||
return TEST_EXIT_SUCCESS; | ||
} | ||
|
||
/* | ||
* XXX: This test should fail neither before the patch | ||
* nor after it. | ||
*/ | ||
static int stackoverflow_during_stackoverflow(void *test_state) | ||
{ | ||
lua_State *L = test_state; | ||
/* | ||
* XXX: `fill_stack` acts here as its own error handler, | ||
* causing the second stack overflow. | ||
*/ | ||
lua_pushcfunction(L, fill_stack); | ||
lua_pushcfunction(L, fill_stack); | ||
int status = lua_pcall(L, 0, 0, -2); | ||
assert_true(status == LUA_ERRERR); | ||
return TEST_EXIT_SUCCESS; | ||
} | ||
|
||
int main(void) | ||
{ | ||
lua_State *L = utils_lua_init(); | ||
const struct test_unit tgroup[] = { | ||
test_unit_def(premature_stackoverflow), | ||
test_unit_def(stackoverflow_during_stackoverflow), | ||
}; | ||
const int test_result = test_run_group(tgroup, L); | ||
utils_lua_close(L); | ||
return test_result; | ||
} |