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 056C314FDB6B; Fri, 22 Aug 2025 09:36:41 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 056C314FDB6B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1755844601; bh=V7TsSugSEuQh/Hdr8s8oulFDwTdAat6469FylW/c4LI=; 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=LlEbcERbiL0vGF9wuRl18yjL/RD7Ug5CvVdW6mHjiCcMmnjWc+FSAcFyUqh4o4IeS bzXeHAYe5uov3BqAqLJfx0sALHeHim3n9p9ga9LQniJY6EOYN4isUi8svmeMgsPH6S E8VrbLCYKbnOZKYqhvVgzpEFoglfPzDf2JAE0UXg= Received: from send105.i.mail.ru (send105.i.mail.ru [89.221.237.200]) (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 60EDC14FDB6B for ; Fri, 22 Aug 2025 09:35:40 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 60EDC14FDB6B Received: by exim-smtp-59d7b54549-zp5cw with esmtpa (envelope-from ) id 1upLND-00000000DVz-2KMf; Fri, 22 Aug 2025 09:35:39 +0300 To: Sergey Bronnikov Date: Fri, 22 Aug 2025 09:36:18 +0300 Message-ID: <429b6cf7a260883bf337b13e30e0c64bc0a70723.1755844191.git.skaplun@tarantool.org> X-Mailer: git-send-email 2.50.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Mailru-Src: smtp X-4EC0790: 10 X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD9CD668969C51240A4154383E622A8E40151D58AEA8E4ED162182A05F5380850406A69C6A2CC73FE963DE06ABAFEAF67054D444AD798950BFB8CDE13A9094B77F40D92EFB1A9252998 X-7FA49CB5: 4BFC5D8501E51E47CA8F6BE7C18995EBF17A87A2884587769615D72176D49C47A6333920E0F9D84FF01C4FAB541DE28FCE208E8FC270FF883B56EE1CD41719AD6EEED3D1F8F94EF624AD3460B7163A6507627EB66F572D0C63D3EDE7CE9F49F504D6AF0AB02B6E8AB3511083BD625FA657FDCB845166BEDE31F443FECF87DDAC6BF926B01C86DB9714A8176813119CCC6BCF00562456A40908BD49AA745F4EB96150814D3F2C6EB9386B6D831821CFCFEDA412B152283F287BD448575E1279A514A8176813119CCC953E0C1C45D6C233E51A9F83D59C908A1A495265874E50822C0CE862CFDDF4E111CEB150E6113A5DB94301A5F42BD15882F519A0EFA9D3BDFD1713539A3C69E83BDB488C0B47A6F318BB8896F27FB42885BD5A8B2055D3F3F17A87A288458776F113C106F3FD22680E36F106248C3CC5EEA1A822253BD6E0 X-C1DE0DAB: B30BEEBCB9DAB3F04F1D36FF21F74672478DEAD3877DCF166D370664109BAC14C15208C767E7A7A1BCC2DF43DD22AB26DB841BC0FD54B826F3134A71D655016B5C00E2E20D82358B5D5BE0742EAEDA04167BBD493139A183B82DCD7C16F34EEA X-C8649E89: 1C3962B70DF3F0ADE00A9FD3E00BEEDF3FED46C3ACD6F73ED3581295AF09D3DF87807E0823442EA2ED31085941D9CD0AF7F820E7B07EA4CFE80CE5004F24F28E13F0D998B7A41691C6D2D46973ED6D1C6ED25DDB4E7CEDE62DC0EA915DEF7D0C69713F3DA683E8D5DC2F84A2275F0B6CBD621E32711466668910B8F6D2BCA4675F4332CA8FE04980913E6812662D5F2A5EAB5682573093F7837F15F2B5E4A70B33F2C28C22F508233FCF178C6DD14203 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu53w8ahmwBjZKM/YPHZyZHvz5uv+WouB9+ObcCpyrx6l7KImUglyhkEat/+ysWwi0gdhEs0JGjl6ggRWTy1haxBpVdbIX1nthFXMZebaIdHP2ghjoIc/363UZI6Kf1ptIMVUcWHxAuDCnGGpr3uMgeu9g= X-DA7885C5: 5B7F14BF3A243653F255D290C0D534F9832B43F0FF792EC16F65787FDBB515FDF9C394A209ABEAA65B1A4C17EAA7BC4BEF2421ABFA55128DAF83EF9164C44C7E X-Mailru-Sender: 689FA8AB762F7393FE9E42A757851DB67B072A35EDE9D1F9404CC6CF53F09F952DC6B3304DC9425BE49D44BB4BD9522A059A1ED8796F048DB274557F927329BE89D5A3BC2B10C37545BD1C3CC395C826B4A721A3011E896F X-Mras: Ok Subject: [Tarantool-patches] [PATCH luajit 2/2] FFI: Fix dangling CType references (again). 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 c64020f3c6d124503213147f2fb47c20335a395b) This patch fixes JIT recording for the vararg calls, that was not fixed in the previous patch. The `ctr` pointer to the child cdata value may become invalid after the ctype state table reallocation in the `crec_call_args()`. This patch preserves `ctr->info` in the separate variable to avoid dereferencing an invalid pointer. Sergey Kaplun: * added the description and the test for the problem Part of tarantool/tarantool#11691 --- src/lj_crecord.c | 11 +-- ...0-dangling-ctype-ref-on-ccall-jit.test.lua | 82 +++++++++++++++++++ 2 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 test/tarantool-tests/lj-1360-dangling-ctype-ref-on-ccall-jit.test.lua diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 935106dc..b016eaec 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -1236,6 +1236,7 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) if (ctype_isfunc(info)) { TRef func = emitir(IRT(IR_FLOAD, tp), J->base[0], IRFL_CDATA_PTR); CType *ctr = ctype_rawchild(cts, ct); + CTInfo ctr_info = ctr->info; /* crec_call_args may invalidate ctr. */ IRType t = crec_ct2irt(cts, ctr); TRef tr; TValue tv; @@ -1243,11 +1244,11 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) tv.u64 = ((uintptr_t)cdata_getptr(cdataptr(cd), (LJ_64 && tp == IRT_P64) ? 8 : 4) >> 2) | U64x(800000000, 00000000); if (tvistrue(lj_tab_get(J->L, cts->miscmap, &tv))) lj_trace_err(J, LJ_TRERR_BLACKL); - if (ctype_isvoid(ctr->info)) { + if (ctype_isvoid(ctr_info)) { t = IRT_NIL; rd->nres = 0; - } else if (!(ctype_isnum(ctr->info) || ctype_isptr(ctr->info) || - ctype_isenum(ctr->info)) || t == IRT_CDATA) { + } else if (!(ctype_isnum(ctr_info) || ctype_isptr(ctr_info) || + ctype_isenum(ctr_info)) || t == IRT_CDATA) { lj_trace_err(J, LJ_TRERR_NYICALL); } if ((info & CTF_VARARG) @@ -1258,7 +1259,7 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) func = emitir(IRT(IR_CARG, IRT_NIL), func, lj_ir_kint(J, ctype_typeid(cts, ct))); tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func); - if (ctype_isbool(ctr->info)) { + if (ctype_isbool(ctr_info)) { if (frame_islua(J->L->base-1) && bc_b(frame_pc(J->L->base-1)[-1]) == 1) { /* Don't check result if ignored. */ tr = TREF_NIL; @@ -1274,7 +1275,7 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) tr = TREF_TRUE; } } else if (t == IRT_PTR || (LJ_64 && t == IRT_P32) || - t == IRT_I64 || t == IRT_U64 || ctype_isenum(ctr->info)) { + t == IRT_I64 || t == IRT_U64 || ctype_isenum(ctr_info)) { TRef trid = lj_ir_kint(J, ctype_cid(info)); tr = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, tr); if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J); diff --git a/test/tarantool-tests/lj-1360-dangling-ctype-ref-on-ccall-jit.test.lua b/test/tarantool-tests/lj-1360-dangling-ctype-ref-on-ccall-jit.test.lua new file mode 100644 index 00000000..388bec6e --- /dev/null +++ b/test/tarantool-tests/lj-1360-dangling-ctype-ref-on-ccall-jit.test.lua @@ -0,0 +1,82 @@ +local tap = require('tap') +local ffi = require('ffi') + +-- This test demonstrates LuaJIT's incorrect behaviour when the +-- reallocation of `cts->tab` strikes during the recording of the +-- setup arguments for the FFI call. +-- Before the patch, the test failed only under ASAN. +-- This file tests the case similar to the +-- , but for the +-- compiler part only. +-- See also https://github.com/LuaJIT/LuaJIT/issues/1360. +local test = tap.test('lj-1360-dangling-ctype-ref-on-ccall'):skipcond({ + ['Impossible to predict the value of cts->top'] = _TARANTOOL, + ['Test requires JIT enabled'] = not jit.status(), +}) + +test:plan(1) + +-- XXX: Declare the structure to increase `cts->top` up to 128 +-- slots. The setting up of function's arguments to the next call +-- will reallocate the `cts->tab` during `lj_ccall_ctid_vararg()` +-- and `ccall_set_args()` will use a dangling reference. +ffi.cdef[[ + struct test { + int a; + int b; + int c; + int d; + int e; + int f; + int g; + int h; + int i; + int j; + int k; + int l; + int m; + int n; + int o; + int p; + int q; + int r; + int s; + int t; + int u; + int v; + int w; + int x; + int y; + int z; + int aa; + int ab; + int ac; + int ad; + }; + // Use an existing function that actually takes no arguments. + // We can declare it however we want. + // Need a vararg function for this issue. + int getppid(...); +]] + +local arg_call = ffi.new('struct test') + +-- Place `getppid` symbol in cache to permit recording. +ffi.C.getppid(0) + +-- Assertions to check the `cts->top` value. +assert(ffi.typeinfo(127), 'cts->top >= 127') +assert(not ffi.typeinfo(128), 'cts->top < 128') + +jit.opt.start('hotloop=1') +local counter = 0 +while counter < 4 do + -- Don't check the result, just check that there is no invalid + -- memory access. + ffi.C.getppid(arg_call) + counter = counter + 1 +end + +test:ok(true, 'no heap-use-after-free in C call') + +test:done(true) -- 2.50.1