From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 10A6213DE5CD; Thu, 5 Jun 2025 12:41:07 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 10A6213DE5CD DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1749116467; bh=HoZ/uflw+OiDeOv2H/DCZtA4v8izsOqc4KUCTsnn8+s=; h=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=hbvE2O9/7xLPUdtTGzgOlqEmdqo7f4NXBWIN6dErRBvxEFy3Qar25GW7LULXYEGJC F/O78eKKpsDH7pj7QidMQMZA8Tw4cxMcVZhC+6rDB45o/AfobLLT0bcldLtwdPlkXz cS9l1aiDuIhiL6b7KAYN49C+ivKlVA9nbAmo6H4M= Received: from send197.i.mail.ru (send197.i.mail.ru [95.163.59.36]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 756C9461F00 for ; Thu, 5 Jun 2025 12:41:05 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 756C9461F00 Received: by exim-smtp-75656d46d5-9nvh8 with esmtpa (envelope-from ) id 1uN75s-00000000BwR-1E4N; Thu, 05 Jun 2025 12:41:04 +0300 To: Sergey Bronnikov Date: Thu, 5 Jun 2025 12:41:05 +0300 Message-ID: <20250605094105.21923-1-skaplun@tarantool.org> X-Mailer: git-send-email 2.49.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Mailru-Src: smtp X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD9851146C857904EABD06CD3671CA88EF63871591067F5DA40182A05F538085040D66E475CE5DB3FF23DE06ABAFEAF6705F4E1E12B3F9C4DA81F23A4732C8219552D7423A3730B98E4 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE79FF7180C05A1FF7CEA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637AC83A81C8FD4AD23D82A6BABE6F325AC2E85FA5F3EDFCBAA7353EFBB5533756680FD86C7FE90CFE5E9586CD9942ADDFE6C2183833EDF8A5FE88F9EA503414129389733CBF5DBD5E913377AFFFEAFD269176DF2183F8FC7C0C26CFBAC0749D213D2E47CDBA5A96583BD4B6F7A4D31EC0BC014FD901B82EE079FA2833FD35BB23D27C277FBC8AE2E8B60CDF180582EB8FBA471835C12D1D977C4224003CC8364762BB6847A3DEAEFB0F43C7A68FF6260569E8FC8737B5C2249EC8D19AE6D49635B68655334FD4449CB9ECD01F8117BC8BEAAAE862A0553A39223F8577A6DFFEA7CAA44A86D94E7BBB043847C11F186F3C59DAA53EE0834AAEE X-C1DE0DAB: 0D63561A33F958A56184DDDB5B7DC99D5002B1117B3ED6960BC940D61BADFCB969995D676B7B4CBE823CB91A9FED034534781492E4B8EEAD5C5DFC4BFF39B799F36E2E0160E5C55395B8A2A0B6518DF68C46860778A80D54AF47762AB4810619 X-C8649E89: 1C3962B70DF3F0ADE00A9FD3E00BEEDF77DD89D51EBB7742D3581295AF09D3DF87807E0823442EA2ED31085941D9CD0AF7F820E7B07EA4CF8F9796B933A15B4920578DD76F6218B78F557919472930FC6EBF2146866FD499715D154A38A044DC4322DC41441C31F034113327482E46824BAF525B98E1E2551DF9DF1A2D550BEA5F4332CA8FE04980913E6812662D5F2A5EAB5682573093F7837F15F2B5E4A70B33F2C28C22F508233FCF178C6DD14203 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu53w8ahmwBjZKM/YPHZyZHvz5uv+WouB9+ObcCpyrx6l7KImUglyhkEat/+ysWwi0gdhEs0JGjl6ggRWTy1haxBpVdbIX1nthFXMZebaIdHP2ghjoIc/363UZI6Kf1ptIMVSykAyseJQ6/SZG49OO6qj0= X-DA7885C5: 27CA0CD510D464AAF255D290C0D534F96FABC03C1FA40C3097E1068A5153AB9718CF90B0B5909D0D5B1A4C17EAA7BC4BEF2421ABFA55128DAF83EF9164C44C7E X-Mailru-Sender: 689FA8AB762F7393FE9E42A757851DB67A9F97C072C2DC79ED10118A6AB548128C9A90A8B7676810E49D44BB4BD9522A059A1ED8796F048DB274557F927329BE89D5A3BC2B10C37545BD1C3CC395C826B4A721A3011E896F X-Mras: Ok Subject: [Tarantool-patches] [PATCH luajit] Fix JIT slot overflow during up-recursion. X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Sergey Kaplun via Tarantool-patches Reply-To: Sergey Kaplun Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" From: Mike Pall Reported by Sergey Kaplun. (cherry picked from commit 048972dbfdb6b441fe8a9bfe4d1f048966579ba8) In the case when LuaJIT is recording the side trace after the up-recursion call, there is no check that the updated `maxslot` value doesn't overflow the `LJ_MAX_JSLOTS` limit. If it records several huge returns in a row, the overflow of the aforementioned limit may occur. This triggers an assertion failure in `rec_check_slots()`. This patch fixes it by adding the corresponding check in the `lj_record_ret()`. Sergey Kaplun: * added the description and the test for the problem Part of tarantool/tarantool#11278 --- Branch: https://github.com/tarantool/luajit/tree/skaplun/lj-1358-jslot-overflow-uprecursion Related issues: * https://github.com/tarantool/tarantool/issues/11278 * https://github.com/LuaJIT/LuaJIT/issues/1358 src/lj_record.c | 3 +- ...j-1358-jslot-overflow-uprecursion.test.lua | 82 +++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 test/tarantool-tests/lj-1358-jslot-overflow-uprecursion.test.lua diff --git a/src/lj_record.c b/src/lj_record.c index d83fa38f..1dd22dac 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -889,7 +889,8 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) lj_trace_err(J, LJ_TRERR_LLEAVE); } else if (J->needsnap) { /* Tailcalled to ff with side-effects. */ lj_trace_err(J, LJ_TRERR_NYIRETL); /* No way to insert snapshot here. */ - } else if (1 + pt->framesize >= LJ_MAX_JSLOTS) { + } else if (1 + pt->framesize >= LJ_MAX_JSLOTS || + J->baseslot + J->maxslot >= LJ_MAX_JSLOTS) { lj_trace_err(J, LJ_TRERR_STACKOV); } else { /* Return to lower frame. Guard for the target we return to. */ TRef trpt = lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); diff --git a/test/tarantool-tests/lj-1358-jslot-overflow-uprecursion.test.lua b/test/tarantool-tests/lj-1358-jslot-overflow-uprecursion.test.lua new file mode 100644 index 00000000..1b151b56 --- /dev/null +++ b/test/tarantool-tests/lj-1358-jslot-overflow-uprecursion.test.lua @@ -0,0 +1,82 @@ +local tap = require('tap') + +-- The test file to demonstrate JIT slots overflow when compiling +-- the return from the trace with up-recursion. +-- See also: https://github.com/LuaJIT/LuaJIT/issues/1358. + +local test = tap.test('lj-1358-jslot-overflow-uprecursion'):skipcond({ + ['Test requires JIT enabled'] = not jit.status(), +}) + +test:plan(1) + +-- The test generates the functions with the following workload: +-- +-- | local uprec_func() +-- | if cond then return end +-- | return 'x', --[[...]] 'x', uprec_func() +-- | end +-- | +-- | local function empty() end +-- | empty('x', --[[...]] 'x', uprec_func()) +-- +-- The recording of the return from `uprec_func()` before the call +-- to `empty()` causes the assertion failure in the +-- `rec_check_slots()`. + +-- Generate a function with many return values plus up-recursion. +local function generate_uprec_payload(n_returns) + local str_func = [[ + local counter = 0 + local function payload_f() + counter = counter + 1 + if counter > 5 then return end + return + ]] + for _ = 1, n_returns do + str_func = str_func .. '"x", ' + end + str_func = str_func .. [[ + payload_f() + end + return payload_f + ]] + local f = assert(loadstring(str_func)) + return f() +end + +-- Generate the necessary number of locals for a huge enough +-- `cbase`. +local function generate_nloc_payload(n_locals) + local str_func = [[ + -- Function to be called after return with all stack slots used. + local function empty() end + empty( + ]] + for _ = 1, n_locals do + str_func = str_func .. '"x", ' + end + str_func = str_func .. [[ + _G.uprec_func() + ) + ]] + local f = assert(loadstring(str_func)) + return f +end + +-- Avoid an unrelated JIT output. +jit.off() +-- 30 * 5 = 150 returned values for the first call. +_G.uprec_func = generate_uprec_payload(30) +-- Plus 100 slots for locals, plus a slot for the function to be +-- called causes JIT stack slots overflow. +local test_func = generate_nloc_payload(100) + +jit.on() +jit.opt.start('hotloop=1', 'hotexit=1', 'recunroll=1') + +test_func() + +test:ok(true, 'no assertion on JIT slots overflow') + +test:done(true) -- 2.49.0