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 7C8F56ECCC; Wed, 9 Nov 2022 20:52:55 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 7C8F56ECCC DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1668016375; bh=q7FtI1MbHWQNgQSgC039/iG5I5DSQ7sbeq1D4O8iiOg=; h=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=u1bgpeF7pOI620rnbPZBgIZZZfJHNzt/NW/q0agFVckOLrZBoeWsrZSktuM6wvJqq 4bkVepMvcshxfVhZn5T+ULgsnwIeP5sY2x+Dc938MgEoQ99rKrkxegQUXcUwm6cEY2 5QMdJiTumesodQe7VMXPh7wpn2SR6uVKPI4thbYk= Received: from smtp59.i.mail.ru (smtp59.i.mail.ru [217.69.128.39]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 5926D6ECCC for ; Wed, 9 Nov 2022 20:52:54 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 5926D6ECCC Received: by smtp59.i.mail.ru with esmtpa (envelope-from ) id 1ospFt-0002cT-8M; Wed, 09 Nov 2022 20:52:53 +0300 To: Maxim Kokryashkin , Igor Munkin Date: Wed, 9 Nov 2022 20:49:48 +0300 Message-Id: <20221109174948.10952-1-skaplun@tarantool.org> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Mailru-Src: smtp X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD95B5D117648C7F15261B311350E21256A7ADBFE1B12BA3A7F182A05F5380850402A4840CF1C524D26B15AB24E22C168A47132A6C4A9EAE22C97F9809081C5B01D X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7A41A3668A00E2636EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F79006373C9FC9F3BACECB908638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D82A9B00397213EFB8350F36683004F2A3117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCECADA55FE5B58BB7A471835C12D1D9774AD6D5ED66289B52BA9C0B312567BB23117882F4460429728776938767073520C24E1E72F37C03A06FD1C55BDD38FC3FD2E47CDBA5A96583BA9C0B312567BB2376E601842F6C81A19E625A9149C048EE41BF15D38FB6CB3A0CB8D3112395442FD8FC6C240DEA7642DBF02ECDB25306B2B78CF848AE20165D0A6AB1C7CE11FEE3B5C78E0E843E24DABA3038C0950A5D36B5C8C57E37DE458B330BD67F2E7D9AF16D1867E19FE14079C09775C1D3CA48CF3D321E7403792E342EB15956EA79C166A417C69337E82CC275ECD9A6C639B01B78DA827A17800CE765B758295022C166731C566533BA786AA5CC5B56E945C8DA X-C1DE0DAB: 0D63561A33F958A54D019870E280C1FD4DB3E5158B5089895F99DAF65F84AD824EAF44D9B582CE87C8A4C02DF684249C2E763F503762DF50F2237FE565727C05 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D345CB6DE26F1654667995E0E8A5272B3D6CAAAEB19E2CC25A27134B295A356A6A3880026F0C1E8F3E91D7E09C32AA3244C8A04C109C4FEFC7CB30F68F55A2ACC49853296C06374E602927AC6DF5659F194 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojbL9S8ysBdXjbs5oj5b60vRWJPCjz4cRh X-Mailru-Sender: 87D5297B137A96FE4AECA001A08BCABA9C8986C384A0C9B93B7CD37570B22873B305FE45D4B78E85525762887713E5F1475755348978188EF9D3679FA3DE6E791CC59163FFD68303B0DAF586E7D11B3E67EA787935ED9F1B X-Mras: Ok Subject: [Tarantool-patches] [PATCH luajit] Ensure correct stack top for OOM error message. 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 ca8d3257bb44e42100c7910c47dcdcf01f494187) `lj_err_mem()` doesn't set up `L->top` for Lua frames, but uses it for pushing error message on the stack. So, when we call some routine that does some allocations, it can raise the OOM error (like `lj_tab_dup()` in `BC_TDUP`) and this error may corrupt stack for unwind in situations when `L->top` < `L->base`. This patch restores `L->top` for Lua frames when raise the error via `lj_err_mem()`. Sergey Kaplun: * added the description and the test for the problem Resolves tarantool/tarantool#3840 Part of tarantool/tarantool#7230 --- Issues: * https://github.com/LuaJIT/LuaJIT/issues/906 * https://github.com/tarantool/tarantool/issues/7230 * https://github.com/tarantool/tarantool/issues/3840 PR: https://github.com/tarantool/tarantool/pull/7915 Branch: https://github.com/tarantool/luajit/tree/skaplun/lj-906-fix-err-mem Red LuaJIT CI for MacOS Release builds is a known issue with self-hosted runners, as Igor has said before. src/lj_err.c | 1 + .../lj-906-fix-err-mem.test.lua | 90 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 test/tarantool-tests/lj-906-fix-err-mem.test.lua diff --git a/src/lj_err.c b/src/lj_err.c index c310daf6..70354489 100644 --- a/src/lj_err.c +++ b/src/lj_err.c @@ -546,6 +546,7 @@ LJ_NOINLINE void lj_err_mem(lua_State *L) { if (L->status == LUA_ERRERR+1) /* Don't touch the stack during lua_open. */ lj_vm_unwind_c(L->cframe, LUA_ERRMEM); + if (curr_funcisL(L)) L->top = curr_topL(L); setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRMEM)); lj_err_throw(L, LUA_ERRMEM); } diff --git a/test/tarantool-tests/lj-906-fix-err-mem.test.lua b/test/tarantool-tests/lj-906-fix-err-mem.test.lua new file mode 100644 index 00000000..a139e1c9 --- /dev/null +++ b/test/tarantool-tests/lj-906-fix-err-mem.test.lua @@ -0,0 +1,90 @@ +local tap = require('tap') +local ffi = require('ffi') +local table_new = require('table.new') + +-- Avoid test to be killed. +require('utils').skipcond(ffi.abi('gc64'), 'test is not GC64 only') + +local test = tap.test('lj-906-fix-err-mem') +test:plan(1) + +local KB = 1024 +local MB = 1024 * KB + +-- The maximum available table size, taking into account created +-- constants for one function. +local TNEW_SIZE = 511 + +local gc_anchor = {} + +-- This function works until raises the error. +local function eat_chunks(size) + -- Need raise the OOM error inside TDUP, not TNEW, so reserve + -- memory for it. + -- luacheck: no unused + local tnew_anchor = table_new(TNEW_SIZE, 0) + while true do + table.insert(gc_anchor, ffi.new('char [?]', size)) + end +end + +-- Function to format inner tab leading to TDUP emitting. +local function format_inner_tab() + local inner_tab = '' + local inner_depth = 128 + -- Repeate table template for TDUP. + for _ = 1, inner_depth do + inner_tab = inner_tab .. '{a =' + end + inner_tab = inner_tab .. '{}' + for _ = 1, inner_depth do + inner_tab = inner_tab .. '},' + end + return inner_tab +end + +local function format_TDUP_chunk() + local big_tab = 'local _ = {\n' + local inner_tab = format_inner_tab() + for _ = 1, TNEW_SIZE do + big_tab = big_tab .. inner_tab .. '\n' + end + big_tab = big_tab .. '}' + return big_tab +end + +local TDUP, err = loadstring(format_TDUP_chunk()) +assert(TDUP, err) + +local function frame_before_TDUP() + -- Stack slots are needed for coredump in case of misbehaviour. + -- luacheck: no unused + local frame_slot1, frame_slot2 + TDUP() + return frame_slot1, frame_slot2 +end + +collectgarbage() +collectgarbage('stop') + +-- Avoid OOM on traces. +jit.off() + +-- Stack slots are needed for coredump in case of misbehaviour. +-- luacheck: no unused +local r, e = pcall(eat_chunks, 8 * MB) +collectgarbage() +pcall(eat_chunks, 8 * KB) +collectgarbage() +pcall(eat_chunks, 8) +collectgarbage() + +pcall(frame_before_TDUP) + +-- Release memory for `tap` functions. +gc_anchor = nil +collectgarbage() + +test:ok(true, 'correctly throw memory error') + +os.exit(test:check() and 0 or 1) -- 2.34.1