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 XmiliaH. (cherry picked from commit 0e66fc9) It is possible to get an infinite loop in a function `snap_usedef` when a `UCLO` makes a tight loop. Sergey Bronnikov: * added the description and the test for the problem Part of tarantool/tarantool#10709
- Loading branch information
Showing
2 changed files
with
88 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
82 changes: 82 additions & 0 deletions
82
test/tarantool-tests/lj-736-BC_UCLO-triggers-infinite-loop.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,82 @@ | ||
local tap = require('tap') | ||
local test = tap.test('lj-736-BC_UCLO-triggers-infinite-loop'):skipcond({ | ||
['Test requires JIT enabled'] = not jit.status(), | ||
}) | ||
|
||
test:plan(2) | ||
|
||
-- Test reproduces an issue when BC_UCLO triggers an infinite loop. | ||
-- See details in https://github.com/LuaJIT/LuaJIT/issues/736. | ||
-- | ||
-- Listing below demonstrates a problem - | ||
-- the bytecode UCLO on the line 13 makes a loop at 0013-0014: | ||
-- | ||
-- - BYTECODE -- bc_uclo.lua:0-20 | ||
-- 0001 KPRI 0 0 | ||
-- 0002 FNEW 1 0 ; bc_uclo.lua:5 | ||
-- 0003 KSHORT 2 1 | ||
-- 0004 KSHORT 3 4 | ||
-- 0005 KSHORT 4 1 | ||
-- 0006 FORI 2 => 0011 | ||
-- 0007 => ISNEN 5 0 ; 2 | ||
-- 0008 JMP 6 => 0010 | ||
-- 0009 UCLO 0 => 0012 | ||
-- 0010 => FORL 2 => 0007 | ||
-- 0011 => UCLO 0 => 0012 | ||
-- 0012 => KPRI 0 0 | ||
-- 0013 UCLO 0 => 0012 | ||
-- 0014 FNEW 1 1 ; bc_uclo.lua:18 | ||
-- 0015 UCLO 0 => 0016 | ||
-- 0016 => RET0 0 1 | ||
|
||
jit.opt.start('hotloop=1') | ||
|
||
local assert_msg = 'Infinite loop is not reproduced.' | ||
local assert = assert | ||
|
||
local function testcase() | ||
-- The code in the first scope `do`/`end` is a prerequisite. | ||
-- It is needed so that we have a trace at the exit from which | ||
-- the creation of the snapshot will begin. | ||
do | ||
-- Upvalue below is not used actually, but it is required | ||
-- for reproducing the problem. | ||
local uv1 -- luacheck: ignore | ||
local _ = function() return uv1 end | ||
|
||
-- The loop below is required for recording a trace. | ||
-- The condition inside a loop executes `goto` to a label | ||
-- outside of the loop when the code executed by JIT and | ||
-- this triggers snapshotting. | ||
for i = 1, 2 do | ||
-- Exit to interpreter once trace is compiled. | ||
if i == 2 then | ||
goto x | ||
end | ||
end | ||
end | ||
|
||
::x:: | ||
do | ||
local uv2 -- luacheck: no unused | ||
|
||
-- `goto` if not executed without a patch and generates an | ||
-- UCLO bytecode that makes an infinite loop in a function | ||
-- `snap_usedef` when patch is not applied. `goto` must point | ||
-- to the label on one of the previous lines. `assert()` is | ||
-- executed when patch is applied. | ||
assert(nil, assert_msg) | ||
goto x | ||
|
||
-- Line below is required, it makes `uv` upvalue, and must be | ||
-- placed after `goto`, otherwise reproducer become broken. | ||
local _ = function() return uv2 end -- luacheck: ignore | ||
end | ||
end | ||
|
||
local ok, err = pcall(testcase) | ||
|
||
test:is(ok, false, 'assertion is triggered in a function with testcase') | ||
test:ok(err:match(assert_msg), 'BC_UCLO does not trigger an infinite loop') | ||
|
||
os.exit(test:check() and 0 or 1) |