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 CB89899FA1B; Wed, 24 Jan 2024 17:16:27 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org CB89899FA1B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1706105787; bh=mfVyxfRFuYfhGRtDHB74NnfHmTyL7rmFElj5PWWlvGY=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=VF+Tf1ShrcoyOcUX20pHGh7nCBO4fIvrrc66Ap6xdXLzsjF91SRLL95KNWQu/zC2O D0sV6pXp1ZvcVYj8Omdh3NugOWjy6nrs2qe2kqezHZchF0g96GxmyQCwm237+t09y3 Ha7rI7w6Ueh1JRcR/DlWrJrqFw0ybceqPjJozSqA= Received: from smtp40.i.mail.ru (smtp40.i.mail.ru [95.163.41.81]) (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 DC44999FA11 for ; Wed, 24 Jan 2024 17:15:25 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org DC44999FA11 Received: by smtp40.i.mail.ru with esmtpa (envelope-from ) id 1rSe2H-00F816-0g; Wed, 24 Jan 2024 17:15:25 +0300 To: Maxim Kokryashkin , Sergey Bronnikov Date: Wed, 24 Jan 2024 17:11:09 +0300 Message-ID: <0d003159c9a1811d98e30a863cc75c11bab658a3.1706104777.git.skaplun@tarantool.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Mailru-Src: smtp X-4EC0790: 10 X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD96A58C36AA2E996497FC6886252B15AA45B61F22128DB277C182A05F538085040B022256312EE0A9C5F80F8888DDCBA2BE32DE46585DE68FAD6010015A9C6BD33 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE75037DDE13FB75316EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F79006372094AD700861FA748638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D8676A5F7FADE6413B7C0160D0738D5DFA117882F4460429724CE54428C33FAD305F5C1EE8F4F765FC6FC43C45D3E35E8FA471835C12D1D9774AD6D5ED66289B52BA9C0B312567BB23117882F446042972877693876707352026055571C92BF10FF6B57BC7E6449061A352F6E88A58FB86F5D81C698A659EA73AA81AA40904B5D9A18204E546F3947C420C44FB56B3298E302FCEF25BFAB3454AD6D5ED66289B523666184CF4C3C14F6136E347CC761E07725E5C173C3A84C399A53BDD9844646EBA3038C0950A5D36B5C8C57E37DE458B330BD67F2E7D9AF16D1867E19FE14079C09775C1D3CA48CFED8438A78DFE0A9E1DD303D21008E298D5E8D9A59859A8B6B372FE9A2E580EFC725E5C173C3A84C361DD96311B40C2D435872C767BF85DA2F004C90652538430E4A6367B16DE6309 X-C1DE0DAB: 0D63561A33F958A5C8DD3CC557667EE49CA07F7D11ADFBAAA7A26B0606B3661FF87CCE6106E1FC07E67D4AC08A07B9B05B63D382EEF4D8969C5DF10A05D560A950611B66E3DA6D700B0A020F03D25A0997E3FB2386030E77 X-C8649E89: 1C3962B70DF3F0ADE00A9FD3E00BEEDF3FED46C3ACD6F73ED3581295AF09D3DF87807E0823442EA2ED31085941D9CD0AF7F820E7B07EA4CF50CD20DB0906963483978BD2DBC13C8259F6AB0AA7A516ABC58DA469434D6DB730FDAC359DA246324BEAD515961AA0A7C158C7F8257D4A292C6A87EDC8512B98A74DFFEFA5DC0E7F02C26D483E81D6BE5EF9655DD6DEA7D65774BB76CC95456EEC5B5AD62611EEC62B5AFB4261A09AF0 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojjPo90oGNxwIh3FK4VIYvzQ== X-Mailru-Sender: 11C2EC085EDE56FAC07928AF2646A7692460E12F5428CE315F80F8888DDCBA2B9BBFB9D4C9B76856DEDBA653FF35249392D99EB8CC7091A70E183A470755BFD208F19895AA18418972D6B4FCE48DF648AE208404248635DF X-Mras: Ok Subject: [Tarantool-patches] [PATCH luajit 2/2] Only emit proper parent references in snapshot replay. 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 Thanks to Peter Cawley. (cherry picked from commit 9bdfd34dccb913777be0efcc6869b6eeb5b9b43b) Assume we have a trace containing the IR instruction: | {sink} tab TNEW #32762 #0 `lj_snap_replay()` assumes that 32762 (0x7ffa) (op1 of TNEW) is a constant reference. It is passed to the `snap_replay_const()` lookup to the IR constant in the 0x7ffa slot. If this slot contains the second part of the IR constant number 0.5029296875 (step of the cycle) in its raw form (0x3fe0180000000000). The 0x18 part is treated as IROp (IR_KGC), and JIT is trying to continue with a store of an invalid GC object, which leads to a crash. This patch checks that only the IRMref IR operand is needed to restore. Sergey Kaplun: * added the description and the test for the problem Part of tarantool/tarantool#9595 --- src/lj_snap.c | 12 ++++--- .../lj-1132-bad-snap-refs.test.lua | 36 +++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 test/tarantool-tests/lj-1132-bad-snap-refs.test.lua diff --git a/src/lj_snap.c b/src/lj_snap.c index 3f0fccec..3eb0cd28 100644 --- a/src/lj_snap.c +++ b/src/lj_snap.c @@ -516,13 +516,15 @@ void lj_snap_replay(jit_State *J, GCtrace *T) IRRef refp = snap_ref(sn); IRIns *ir = &T->ir[refp]; if (regsp_reg(ir->r) == RID_SUNK) { + uint8_t m; if (J->slot[snap_slot(sn)] != snap_slot(sn)) continue; pass23 = 1; lj_assertJ(ir->o == IR_TNEW || ir->o == IR_TDUP || ir->o == IR_CNEW || ir->o == IR_CNEWI, "sunk parent IR %04d has bad op %d", refp - REF_BIAS, ir->o); - if (ir->op1 >= T->nk) snap_pref(J, T, map, nent, seen, ir->op1); - if (ir->op2 >= T->nk) snap_pref(J, T, map, nent, seen, ir->op2); + m = lj_ir_mode[ir->o]; + if (irm_op1(m) == IRMref) snap_pref(J, T, map, nent, seen, ir->op1); + if (irm_op2(m) == IRMref) snap_pref(J, T, map, nent, seen, ir->op2); if (LJ_HASFFI && ir->o == IR_CNEWI) { if (LJ_32 && refp+1 < T->nins && (ir+1)->o == IR_HIOP) snap_pref(J, T, map, nent, seen, (ir+1)->op2); @@ -550,14 +552,16 @@ void lj_snap_replay(jit_State *J, GCtrace *T) IRIns *ir = &T->ir[refp]; if (regsp_reg(ir->r) == RID_SUNK) { TRef op1, op2; + uint8_t m; if (J->slot[snap_slot(sn)] != snap_slot(sn)) { /* De-dup allocs. */ J->slot[snap_slot(sn)] = J->slot[J->slot[snap_slot(sn)]]; continue; } op1 = ir->op1; - if (op1 >= T->nk) op1 = snap_pref(J, T, map, nent, seen, op1); + m = lj_ir_mode[ir->o]; + if (irm_op1(m) == IRMref) op1 = snap_pref(J, T, map, nent, seen, op1); op2 = ir->op2; - if (op2 >= T->nk) op2 = snap_pref(J, T, map, nent, seen, op2); + if (irm_op2(m) == IRMref) op2 = snap_pref(J, T, map, nent, seen, op2); if (LJ_HASFFI && ir->o == IR_CNEWI) { if (LJ_32 && refp+1 < T->nins && (ir+1)->o == IR_HIOP) { lj_needsplit(J); /* Emit joining HIOP. */ diff --git a/test/tarantool-tests/lj-1132-bad-snap-refs.test.lua b/test/tarantool-tests/lj-1132-bad-snap-refs.test.lua new file mode 100644 index 00000000..1f2b5400 --- /dev/null +++ b/test/tarantool-tests/lj-1132-bad-snap-refs.test.lua @@ -0,0 +1,36 @@ +local tap = require('tap') + +-- Test file to demonstrate LuaJIT's crash in cases of sunk +-- restore for huge tables. +-- See also https://github.com/LuaJIT/LuaJIT/issues/1132. + +local test = tap.test('lj-1132-bad-snap-refs'):skipcond({ + ['Test requires JIT enabled'] = not jit.status(), +}) + +test:plan(1) + +local table_new = require('table.new') + +jit.opt.start('hotloop=1', 'hotexit=1') + +local result_tab +-- Create a trace containing the IR instruction: +-- | {sink} tab TNEW #32762 #0 +-- `lj_snap_replay()` assumes that 32762 (0x7ffa) (op1 of TNEW) is +-- a constant reference. It is passed to the `snap_replay_const()` +-- lookup to the IR constant in the 0x7ffa slot. +-- This slot contains the second part of the IR constant +-- number 0.5029296875 (step of the cycle) in its raw form +-- (0x3fe0180000000000). The 0x18 part is treated as IROp +-- (IR_KGC), and JIT is trying to continue with a store of an +-- invalid GC object, which leads to a crash. +for i = 1, 2.5, 0.5029296875 do + local sunk_tab = table_new(0x7ff9, 0) + -- Force the side exit with restoration of the sunk table. + if i > 2 then result_tab = sunk_tab end +end + +test:ok(type(result_tab) == 'table', 'no crash during sunk restore') + +test:done(true) -- 2.43.0