forked from LuaJIT/LuaJIT
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Restore state when recording __concat metamethod throws an error.
Thanks to Sergey Kaplun. (cherry picked from commit 7421a1b) Since neither `rec_cat()` nor `lj_record_ret()` restore the Lua stack, if the error is raised, it leads either to a crash in `BC_RET` or to the "unbalanced stack" assertion failure. This patch protects the `rec_mm_arith()`, which can raise an error. Its caller returns the negated error code to be rethrown in case of the caught error. Sergey Kaplun: * added the description and the test for the problem Part of tarantool/tarantool#10199
- Loading branch information
Showing
2 changed files
with
69 additions
and
2 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
45 changes: 45 additions & 0 deletions
45
test/tarantool-tests/lj-1234-err-in-record-concat.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,45 @@ | ||
local tap = require('tap') | ||
|
||
-- Test file to demonstrate the crash during the concat recording | ||
-- if it throws an error. | ||
-- See also: https://github.com/LuaJIT/LuaJIT/issues/1234. | ||
|
||
local test = tap.test('lj-1234-err-in-record-concat'):skipcond({ | ||
['Test requires JIT enabled'] = not jit.status(), | ||
}) | ||
|
||
test:plan(2) | ||
|
||
jit.opt.start('hotloop=1') | ||
|
||
local __concat = function() | ||
return '' | ||
end | ||
|
||
-- Need to use metamethod call in the concat recording. | ||
-- We may use any object with a metamethod, but let's use a table | ||
-- as the most common one. | ||
local concatable_t = setmetatable({}, { | ||
__concat = __concat, | ||
}) | ||
|
||
local function test_concat_p() | ||
local counter = 0 | ||
while counter < 1 do | ||
counter = counter + 1 | ||
-- The first result is placed on the Lua stack before the | ||
-- error is raised. When the error is raised, it is handled by | ||
-- the trace recorder, but since neither `rec_cat()` nor | ||
-- `lj_record_ret()` restore the Lua stack (before the patch), | ||
-- it becomes unbalanced after the instruction recording | ||
-- attempt. | ||
local _ = {} .. (concatable_t .. concatable_t) | ||
end | ||
end | ||
|
||
local result, errmsg = pcall(test_concat_p) | ||
|
||
test:ok(not result, 'the error is raised') | ||
test:like(errmsg, 'attempt to concatenate a table value', 'correct error') | ||
|
||
test:done(true) |