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.
Fix stack allocation after on-trace stack check.
(cherry picked from commit 204cee2) It is possible that a snapshot topslot is less than the possible topslot of the Lua stack. In that case, if the Lua stack overflows in `lj_vmevent_prepare()`, the error is raised inside `lj_vm_exit_handler()`, which has no corresponding DWARF eh_frame [1], so it leads to the crash. This patch fix-ups the topslot of the snapshot on trace exit to the maximum possible one. Sergey Kaplun: * added the description and the test for the problem [1]: https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html Part of tarantool/tarantool#10199 Reviewed-by: Sergey Bronnikov <[email protected]> Reviewed-by: Maxim Kokryashkin <[email protected]> Signed-off-by: Sergey Kaplun <[email protected]>
- Loading branch information
Showing
2 changed files
with
58 additions
and
1 deletion.
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
53 changes: 53 additions & 0 deletions
53
test/tarantool-tests/fix-stack-alloc-on-trace-exit.test.lua
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,53 @@ | ||
local tap = require('tap') | ||
|
||
-- Test file to demonstrate incorrect Lua stack restoration on | ||
-- exit from trace by the stack overflow. | ||
|
||
local test = tap.test('fix-stack-alloc-on-trace-exit'):skipcond({ | ||
['Test requires JIT enabled'] = not jit.status(), | ||
}) | ||
|
||
local jit_dump = require('jit.dump') | ||
|
||
test:plan(2) | ||
|
||
-- Before the patch, it is possible that a snapshot topslot is | ||
-- less than the possible topslot of the Lua stack. In that case, | ||
-- if the Lua stack overflows in `lj_vmevent_prepare()`, the error | ||
-- is raised inside `lj_vm_exit_handler()`, which has no | ||
-- corresponding DWARF eh_frame, so it leads to the crash. | ||
|
||
-- Need for the stack growing in `lj_vmevent_prepare`. | ||
jit_dump.start('x', '/dev/null') | ||
|
||
-- Create a coroutine with a fixed stack size. | ||
local coro = coroutine.create(function() | ||
jit.opt.start('hotloop=1', 'hotexit=1', 'callunroll=1') | ||
|
||
-- `math.modf` recording is NYI. | ||
-- Local `math_modf` simplifies `jit.dump()` output. | ||
local math_modf = math.modf | ||
|
||
local function trace(n) | ||
n = n + 1 | ||
-- luacheck: ignore | ||
-- Start a side trace here. | ||
if n % 2 == 0 then end | ||
-- Stop the recording of the side trace and a main trace, | ||
-- stitching. | ||
math_modf(1, 1) | ||
-- Grow stack, avoid tail calls. | ||
local unused = trace(n) | ||
return unused | ||
end | ||
|
||
local n = 0 | ||
trace(n) | ||
end) | ||
|
||
local result, errmsg = coroutine.resume(coro) | ||
|
||
test:ok(not result, 'correct status and no crash') | ||
test:like(errmsg, 'stack overflow', 'correct error message') | ||
|
||
test:done(true) |