From: Sergey Bronnikov via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: Sergey Kaplun <skaplun@tarantool.org>,
Sergey Bronnikov <estetus@gmail.com>
Cc: tarantool-patches@dev.tarantool.org
Subject: Re: [Tarantool-patches] [PATCH luajit 3/3][v2] Add stack check to pcall/xpcall.
Date: Wed, 11 Mar 2026 17:37:36 +0300 [thread overview]
Message-ID: <5f1d22b9-2fd2-4036-8011-3f721c0abbe7@tarantool.org> (raw)
In-Reply-To: <aYxY2jP8eBh6Z6MF@root>
[-- Attachment #1: Type: text/plain, Size: 8615 bytes --]
Hi, Sergey,
thanks for review!
Sergey
On 2/11/26 13:24, Sergey Kaplun via Tarantool-patches wrote:
> Hi, Sergey!
> Thanks for the patch!
> Please consider my comments below.
>
> On 10.12.25, Sergey Bronnikov wrote:
>> From: Mike Pall <mike>
>>
>> Analyzed by Peter Cawley.
>>
>> (cherry picked from commit a4c1640432a9d8a60624cdc8065b15078c228e36)
>>
>> In the previous commit ("LJ_FR2: Fix stack checks in vararg calls.")
>> stack overflow for vararg functions and metamethod invocations
>> was fixed partially and there are still cases where stack overflow
>> happens, see comments in the test. The patch fixes the issue by
> Please describe the issue regardless previous commit. Just mentioned
> missing stack checks for `pcall()`, `xpcall()` is enough.
Updated commit message:
Add stack check to pcall/xpcall.
Analyzed by Peter Cawley.
(cherry picked from commit a4c1640432a9d8a60624cdc8065b15078c228e36)
The patch adds the stack check to fast functions `pcall()` and
`xpcall()`.
Sergey Bronnikov:
* added the description and the test for the problem
Part of tarantool/tarantool#12134
>> adding the stack check to fast functions `pcall()` and `xpcall()`.
>>
>> Sergey Bronnikov:
>> * added the description and the test for the problem
>>
>> Part of tarantool/tarantool#12134
>> ---
>> src/vm_arm.dasc | 7 +++++
>> src/vm_arm64.dasc | 8 +++++
>> src/vm_mips.dasc | 10 +++++-
>> src/vm_mips64.dasc | 14 +++++++--
>> src/vm_ppc.dasc | 9 ++++++
>> src/vm_x64.dasc | 6 ++++
>> src/vm_x86.dasc | 6 ++++
>> ...048-fix-stack-checks-vararg-calls.test.lua | 31 ++++++++++++++++++-
>> 8 files changed, 86 insertions(+), 5 deletions(-)
>>
>> diff --git a/src/vm_arm.dasc b/src/vm_arm.dasc
>> index 7095e660..efe9dcb2 100644
>> --- a/src/vm_arm.dasc
>> +++ b/src/vm_arm.dasc
> <snipped>
>
>> diff --git a/src/vm_arm64.dasc b/src/vm_arm64.dasc
>> index cf8e575a..53ff7162 100644
>> --- a/src/vm_arm64.dasc
>> +++ b/src/vm_arm64.dasc
> <snipped>
>
>> diff --git a/src/vm_mips.dasc b/src/vm_mips.dasc
>> index 32caabf7..69d09d52 100644
>> --- a/src/vm_mips.dasc
>> +++ b/src/vm_mips.dasc
> <snipped>
>
>> diff --git a/src/vm_mips64.dasc b/src/vm_mips64.dasc
>> index 6c2975b4..4e60ee07 100644
>> --- a/src/vm_mips64.dasc
>> +++ b/src/vm_mips64.dasc
>> @@ -1418,8 +1418,12 @@ static void build_subroutines(BuildCtx *ctx)
>> |//-- Base library: catch errors ----------------------------------------
>> |
>> |.ffunc pcall
>> + | ld TMP1, L->maxstack
>> + | daddu TMP2, BASE,NARGS8:RC
>> + | sltu AT, TMP1, TMP2
>> + | bnez AT, ->fff_fallback
>> + |. lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH)
>> | daddiuNARGS8:RC,NARGS8:RC, -8
>> - | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH)
>> | bltzNARGS8:RC, ->fff_fallback
>> |. move TMP2, BASE
>> | daddiu BASE, BASE, 16
>> @@ -1440,8 +1444,12 @@ static void build_subroutines(BuildCtx *ctx)
>> |. nop
>> |
>> |.ffunc xpcall
>> - | daddiuNARGS8:TMP0,NARGS8:RC, -16
> This change is incorrect.
> It wipes out the first patch in the series.
Sorry, my bad.
--- a/src/vm_mips64.dasc
+++ b/src/vm_mips64.dasc
@@ -1449,7 +1449,7 @@ static void build_subroutines(BuildCtx *ctx)
| sltu AT, TMP1, TMP2
| bnez AT, ->fff_fallback
|. ld CARG1, 0(BASE)
- | daddiu NARGS8:RC, NARGS8:RC, -16
+ | daddiu NARGS8:TMP0, NARGS8:RC, -16
| ld CARG2, 8(BASE)
| bltz NARGS8:TMP0, ->fff_fallback
|. lbu TMP1, DISPATCH_GL(hookmask)(DISPATCH)
>> - | ld CARG1, 0(BASE)
>> + | ld TMP1, L->maxstack
>> + | daddu TMP2, BASE,NARGS8:RC
>> + | sltu AT, TMP1, TMP2
>> + | bnez AT, ->fff_fallback
>> + |. ld CARG1, 0(BASE)
>> + | daddiuNARGS8:RC,NARGS8:RC, -16
>> | ld CARG2, 8(BASE)
>> | bltzNARGS8:TMP0, ->fff_fallback
>> |. lbu TMP1, DISPATCH_GL(hookmask)(DISPATCH)
>> diff --git a/src/vm_ppc.dasc b/src/vm_ppc.dasc
>> index 980ad897..f2ea933b 100644
>> --- a/src/vm_ppc.dasc
>> +++ b/src/vm_ppc.dasc
> <snipped>
>
>> diff --git a/src/vm_x64.dasc b/src/vm_x64.dasc
>> index d5296759..141f5f82 100644
>> --- a/src/vm_x64.dasc
>> +++ b/src/vm_x64.dasc
> <snipped>
>
>> diff --git a/src/vm_x86.dasc b/src/vm_x86.dasc
>> index b043b830..1ba5abce 100644
>> --- a/src/vm_x86.dasc
>> +++ b/src/vm_x86.dasc
> <snipped>
>
>> diff --git a/test/tarantool-tests/lj-1048-fix-stack-checks-vararg-calls.test.lua b/test/tarantool-tests/lj-1048-fix-stack-checks-vararg-calls.test.lua
>> index d471d41e..b135042b 100644
>> --- a/test/tarantool-tests/lj-1048-fix-stack-checks-vararg-calls.test.lua
>> +++ b/test/tarantool-tests/lj-1048-fix-stack-checks-vararg-calls.test.lua
>> @@ -1,4 +1,5 @@
>> local tap = require('tap')
>> +local ffi = require('ffi')
>>
>> -- A test file to demonstrate a stack overflow in `pcall()` in
>> -- some cases, see below testcase descriptions.
>> @@ -7,7 +8,7 @@ local test = tap.test('lj-1048-fix-stack-checks-vararg-calls'):skipcond({
>> ['Test requires JIT enabled'] = not jit.status(),
>> })
>>
>> -test:plan(2)
>> +test:plan(4)
> This patch covers only `pcall()` cases, please add the same tests for
> `xpcall()` (I suppose the most simple is `xpcall()` as `__call`
> metamethod).
Added:
diff --git
a/test/tarantool-tests/lj-1048-fix-stack-checks-vararg-calls.test.lua
b/test/tarantool-tests/lj-1048-fix-stack-checks-vararg-calls.test.lua
index 0ce3c756..8f45941c 100644
--- a/test/tarantool-tests/lj-1048-fix-stack-checks-vararg-calls.test.lua
+++ b/test/tarantool-tests/lj-1048-fix-stack-checks-vararg-calls.test.lua
@@ -6,7 +6,7 @@ local ffi = require('ffi')
-- See also https://github.com/LuaJIT/LuaJIT/issues/1048.
local test = tap.test('lj-1048-fix-stack-checks-vararg-calls')
-test:plan(4)
+test:plan(5)
-- The test case demonstrates a segmentation fault due to stack
-- overflow by recursive calling `pcall()`. The functions are
@@ -51,12 +51,16 @@ pcall(coroutine.wrap(looper), prober_2, 0)
test:ok(true, 'no stack overflow with metamethod')
--- The testcase demonstrates a stack overflow in
+-- The testcases demonstrates a stack overflow in
-- `pcall()`/xpcall()` triggered using metamethod `__call`.
t = coroutine.wrap(setmetatable)({}, { __call = pcall })
-test:ok(true, 'no stack overflow with metamethod __call')
+test:ok(true, 'no stack overflow with metamethod __call with pcall()')
+
+t = coroutine.wrap(setmetatable)({}, { __call = xpcall })
+
+test:ok(true, 'no stack overflow with metamethod __call with xpcall()')
-- The testcase demonstrates a stack overflow in
-- `pcall()`/`xpcall()` similar to the first testcase, but it is
>>
>> -- The testcase demonstrate a segmentation fault due to stack
>> -- overflow by recursive calling `pcall()`. The functions are
>> @@ -50,4 +51,32 @@ pcall(coroutine.wrap(looper), prober_2, 0)
>>
>> test:ok(true, 'no stack overflow with metamethod')
>>
>> +-- The testcase demonstrate a stack overflow in
> Typo: s/demonstrate/demonstrates/
Fixed.
>> +-- `pcall()`/xpcall()` triggered using metamethod `__call`.
>> +
>> +t = setmetatable({}, { __call = pcall })()
> It's better to do this at the separate Lua stack, i.e. inside
> `coroutine.wrap()`.
Updated.
-- `pcall()`/xpcall()` triggered using metamethod `__call`.
-t = setmetatable({}, { __call = pcall })()
+t = coroutine.wrap(setmetatable)({}, { __call = pcall })
>> +
>> +test:ok(true, 'no stack overflow with metamethod __call')
>> +
>> +-- The testcase demonstrate a stack overflow in
> Typo: s/demonstrate/demonstrates/
Fixed.
>> +-- `pcall()`/`xpcall()` similar to the first testcase, but it is
>> +-- triggered using `unpack()`.
>> +
>> +t = {}
>> +local function f()
>> + return pcall(unpack(t))
>> +end
>> +
> Please explain the amount of necessary iterations of calls.
After a small research we found that issue cannot be reproduced in
LuaJIT GC32 flavors.
N_ITERATION should be equal to at least 200 for reproducing.
The problem reproduced better under Valgrind than ASAN.
>> +local N_ITERATIONS = 100
>> +if ffi.abi('gc64') then
>> + N_ITERATIONS = 180
>> +end
>> +
>> +for i = 1, N_ITERATIONS do
>> + t[i], t[i + 1], t[i + 2] = pcall, pairs, {}
> Let's use `type` here instead of pairs.
Updated.
>> + coroutine.wrap(f)()
>> +end
>> +
>> +test:ok(true, 'no stack overflow with unpacked pcalls')
>> +
>> test:done(true)
>> --
>> 2.43.0
>>
[-- Attachment #2: Type: text/html, Size: 13510 bytes --]
prev parent reply other threads:[~2026-03-11 14:37 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-10 7:23 [Tarantool-patches] [PATCH luajit 0/3][v2] Fix stack overflow in pcall/xpcall Sergey Bronnikov via Tarantool-patches
2025-12-10 7:23 ` [Tarantool-patches] [PATCH luajit 1/3] MIPS64: Fix xpcall() error case Sergey Bronnikov via Tarantool-patches
2026-02-11 7:17 ` Sergey Kaplun via Tarantool-patches
2026-02-12 13:26 ` Sergey Bronnikov via Tarantool-patches
2025-12-10 7:23 ` [Tarantool-patches] [PATCH luajit 2/3][v2] LJ_FR2: Fix stack checks in vararg calls Sergey Bronnikov via Tarantool-patches
2026-02-11 8:30 ` Sergey Kaplun via Tarantool-patches
2026-02-16 7:20 ` Sergey Bronnikov via Tarantool-patches
2026-03-04 9:49 ` Sergey Kaplun via Tarantool-patches
2026-03-12 6:52 ` Sergey Bronnikov via Tarantool-patches
2025-12-10 7:23 ` [Tarantool-patches] [PATCH luajit 3/3][v2] Add stack check to pcall/xpcall Sergey Bronnikov via Tarantool-patches
2026-02-11 10:24 ` Sergey Kaplun via Tarantool-patches
2026-03-11 14:37 ` Sergey Bronnikov via Tarantool-patches [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5f1d22b9-2fd2-4036-8011-3f721c0abbe7@tarantool.org \
--to=tarantool-patches@dev.tarantool.org \
--cc=estetus@gmail.com \
--cc=sergeyb@tarantool.org \
--cc=skaplun@tarantool.org \
--subject='Re: [Tarantool-patches] [PATCH luajit 3/3][v2] Add stack check to pcall/xpcall.' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox