* [Tarantool-patches] [PATCH luajit 0/3][v2] Fix stack overflow in pcall/xpcall
@ 2025-12-10 7:23 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
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Sergey Bronnikov via Tarantool-patches @ 2025-12-10 7:23 UTC (permalink / raw)
To: tarantool-patches, Sergey Kaplun
The proposed patches fixes stack overflow in pcall/xpcall.
Related issues:
- https://github.com/LuaJIT/LuaJIT/issues/1048
- https://github.com/tarantool/tarantool/issues/11691
Git branch: https://github.com/tarantool/luajit/tree/ligurio/gh-xxxx-fix-stack-checks-in-vararg-calls
Changes in v2:
- Added patch for MIPS64
- Fixed issues reported on review
Mike Pall (3):
MIPS64: Fix xpcall() error case.
LJ_FR2: Fix stack checks in vararg calls.
Add stack check to pcall/xpcall.
src/lj_def.h | 2 +-
src/lj_dispatch.c | 2 +-
src/vm_arm.dasc | 7 ++
src/vm_arm64.dasc | 9 ++
src/vm_mips.dasc | 10 ++-
src/vm_mips64.dasc | 16 +++-
src/vm_ppc.dasc | 9 ++
src/vm_x64.dasc | 6 ++
src/vm_x86.dasc | 6 ++
...048-fix-stack-checks-vararg-calls.test.lua | 82 +++++++++++++++++++
10 files changed, 143 insertions(+), 6 deletions(-)
create mode 100644 test/tarantool-tests/lj-1048-fix-stack-checks-vararg-calls.test.lua
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Tarantool-patches] [PATCH luajit 1/3] MIPS64: Fix xpcall() error case.
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 ` 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
2025-12-10 7:23 ` [Tarantool-patches] [PATCH luajit 3/3][v2] Add stack check to pcall/xpcall Sergey Bronnikov via Tarantool-patches
2 siblings, 0 replies; 4+ messages in thread
From: Sergey Bronnikov via Tarantool-patches @ 2025-12-10 7:23 UTC (permalink / raw)
To: tarantool-patches, Sergey Kaplun
From: Mike Pall <mike>
Thanks to François Perrad and Stefan Pejic.
(cherry picked from commit ea7071d3c30b6432bfe6f8a9d263e0285cec25e3)
The patch fixes `xpcall()` segfaults on MIPS64 commit. The similar
patch for ARM64 has been backported previously, see the commit
af889e4608e6eca495dd85e6161d8bcd7d3628e6 ("ARM64: Fix xpcall()
error case (really).").
Sergey Bronnikov:
* added the description
Part of tarantool/tarantool#12134
---
src/vm_mips64.dasc | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/vm_mips64.dasc b/src/vm_mips64.dasc
index 44fba36c..da187a7a 100644
--- a/src/vm_mips64.dasc
+++ b/src/vm_mips64.dasc
@@ -1440,15 +1440,16 @@ static void build_subroutines(BuildCtx *ctx)
|. nop
|
|.ffunc xpcall
- | daddiu NARGS8:RC, NARGS8:RC, -16
+ | daddiu NARGS8:TMP0, NARGS8:RC, -16
| ld CARG1, 0(BASE)
| ld CARG2, 8(BASE)
- | bltz NARGS8:RC, ->fff_fallback
+ | bltz NARGS8:TMP0, ->fff_fallback
|. lbu TMP1, DISPATCH_GL(hookmask)(DISPATCH)
| gettp AT, CARG2
| daddiu AT, AT, -LJ_TFUNC
| bnez AT, ->fff_fallback // Traceback must be a function.
|. move TMP2, BASE
+ | move NARGS8:RC, NARGS8:TMP0
| daddiu BASE, BASE, 24
| // Remember active hook before pcall.
| srl TMP3, TMP3, HOOK_ACTIVE_SHIFT
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Tarantool-patches] [PATCH luajit 2/3][v2] LJ_FR2: Fix stack checks in vararg calls.
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
@ 2025-12-10 7:23 ` 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
2 siblings, 0 replies; 4+ messages in thread
From: Sergey Bronnikov via Tarantool-patches @ 2025-12-10 7:23 UTC (permalink / raw)
To: tarantool-patches, Sergey Kaplun
From: Mike Pall <mike>
Thanks to Peter Cawley.
(cherry picked from commit d1a2fef8a8f53b0055ee041f7f63d83a27444ffa)
Stack overflow can cause a segmentation fault in vararg
function on ARM64 and MIPS64 in LJ_FR2 mode. This happen
because stack check in BC_IFUNCV is off by one on these
platforms without the patch. The original stack check
for ARM64 and MIPS64 was incorrect:
| RA == BASE + (RD=NARGS)*8 + framesize * 8 >= maxstack
while stack check on x86_64 is correct and therefore is
not affected by the problem:
| RA == BASE + (RD=NARGS+1)*8 + framesize * 8 +8 > maxstack
The patch partially fixes aforementioned issue by
bumping LJ_STACK_EXTRA by 1 to give a space to write
the entire frame link and fixing a number of last
free slot in the stack (LJ_FR2 summand adjustment).
A fixup for a number of required slots in `call_init()` was added
for consistency with non-gc64 flavor.
Sergey Bronnikov:
* added the description and the test for the problem
Part of tarantool/tarantool#12134
---
src/lj_def.h | 2 +-
src/lj_dispatch.c | 2 +-
src/vm_arm64.dasc | 1 +
src/vm_mips64.dasc | 1 +
...048-fix-stack-checks-vararg-calls.test.lua | 53 +++++++++++++++++++
5 files changed, 57 insertions(+), 2 deletions(-)
create mode 100644 test/tarantool-tests/lj-1048-fix-stack-checks-vararg-calls.test.lua
diff --git a/src/lj_def.h b/src/lj_def.h
index a5bca6b0..7e4f251e 100644
--- a/src/lj_def.h
+++ b/src/lj_def.h
@@ -69,7 +69,7 @@ typedef unsigned int uintptr_t;
#define LJ_MAX_UPVAL 60 /* Max. # of upvalues. */
#define LJ_MAX_IDXCHAIN 100 /* __index/__newindex chain limit. */
-#define LJ_STACK_EXTRA (5+2*LJ_FR2) /* Extra stack space (metamethods). */
+#define LJ_STACK_EXTRA (5+3*LJ_FR2) /* Extra stack space (metamethods). */
#define LJ_NUM_CBPAGE 1 /* Number of FFI callback pages. */
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c
index a44a5adf..431cb3c2 100644
--- a/src/lj_dispatch.c
+++ b/src/lj_dispatch.c
@@ -453,7 +453,7 @@ static int call_init(lua_State *L, GCfunc *fn)
int numparams = pt->numparams;
int gotparams = (int)(L->top - L->base);
int need = pt->framesize;
- if ((pt->flags & PROTO_VARARG)) need += 1+gotparams;
+ if ((pt->flags & PROTO_VARARG)) need += 1+LJ_FR2+gotparams;
lj_state_checkstack(L, (MSize)need);
numparams -= gotparams;
return numparams >= 0 ? numparams : 0;
diff --git a/src/vm_arm64.dasc b/src/vm_arm64.dasc
index c5f0a7a7..cf8e575a 100644
--- a/src/vm_arm64.dasc
+++ b/src/vm_arm64.dasc
@@ -3779,6 +3779,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| add TMP2, BASE, RC
| add LFUNC:CARG3, CARG3, TMP0, lsl #47
| add RA, RA, RC
+ | sub CARG1, CARG1, #8
| add TMP0, RC, #16+FRAME_VARG
| str LFUNC:CARG3, [TMP2], #8 // Store (tagged) copy of LFUNC.
| ldr KBASE, [PC, #-4+PC2PROTO(k)]
diff --git a/src/vm_mips64.dasc b/src/vm_mips64.dasc
index da187a7a..6c2975b4 100644
--- a/src/vm_mips64.dasc
+++ b/src/vm_mips64.dasc
@@ -5268,6 +5268,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| settp LFUNC:RB, TMP0
| daddu TMP0, RA, RC
| sd LFUNC:RB, 0(TMP1) // Store (tagged) copy of LFUNC.
+ | daddiu TMP2, TMP2, -8
| daddiu TMP3, RC, 16+FRAME_VARG
| sltu AT, TMP0, TMP2
| ld KBASE, -4+PC2PROTO(k)(PC)
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
new file mode 100644
index 00000000..d471d41e
--- /dev/null
+++ b/test/tarantool-tests/lj-1048-fix-stack-checks-vararg-calls.test.lua
@@ -0,0 +1,53 @@
+local tap = require('tap')
+
+-- A test file to demonstrate a stack overflow in `pcall()` in
+-- some cases, see below testcase descriptions.
+-- See also https://github.com/LuaJIT/LuaJIT/issues/1048.
+local test = tap.test('lj-1048-fix-stack-checks-vararg-calls'):skipcond({
+ ['Test requires JIT enabled'] = not jit.status(),
+})
+
+test:plan(2)
+
+-- The testcase demonstrate a segmentation fault due to stack
+-- overflow by recursive calling `pcall()`. The functions are
+-- vararg because stack check in BC_IFUNCV is off by one on ARM64
+-- and MIPS64 without the patch.
+local function prober_1(...) -- luacheck: no unused
+ -- Any fast function can be used as metamethod, but `type` is
+ -- convenient here because it works fast and can be used with
+ -- any data type. Lua function cannot be used since it
+ -- will check the stack on each invocation.
+ pcall(pcall, pcall, pcall, pcall, pcall, pcall, pcall, pcall, type, 0)
+end
+
+local function looper(prober, n, ...)
+ prober(...)
+ return looper(prober, n + 1, n, ...)
+end
+
+pcall(coroutine.wrap(looper), prober_1, 0)
+
+test:ok(true, 'no stack overflow with recursive pcall')
+
+-- The testcase demonstrate a segmentation fault due to stack
+-- overflow when `pcall()` is used as `__newindex` metamethod.
+-- The function is vararg because stack check in BC_IFUNCV is off
+-- by one on ARM64 and MIPS64 without the patch.
+
+-- Any fast function can be used as metamethod, but `type` is
+-- convenient here because it works fast and can be used with
+-- any data type. Lua function cannot be used since it
+-- will check the stack on each invocation.
+local t = setmetatable({}, { __newindex = pcall, __call = type })
+
+local function prober_2(...) -- luacheck: no unused
+ -- Invokes `pcall(t, t, t)`.
+ t[t] = t
+end
+
+pcall(coroutine.wrap(looper), prober_2, 0)
+
+test:ok(true, 'no stack overflow with metamethod')
+
+test:done(true)
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Tarantool-patches] [PATCH luajit 3/3][v2] Add stack check to pcall/xpcall.
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
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
@ 2025-12-10 7:23 ` Sergey Bronnikov via Tarantool-patches
2 siblings, 0 replies; 4+ messages in thread
From: Sergey Bronnikov via Tarantool-patches @ 2025-12-10 7:23 UTC (permalink / raw)
To: tarantool-patches, Sergey Kaplun
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
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
@@ -1201,8 +1201,11 @@ static void build_subroutines(BuildCtx *ctx)
|//-- Base library: catch errors ----------------------------------------
|
|.ffunc pcall
+ | ldr RB, L->maxstack
+ | add INS, BASE, NARGS8:RC
| ldrb RA, [DISPATCH, #DISPATCH_GL(hookmask)]
| cmp NARGS8:RC, #8
+ | cmphs RB, INS
| blo ->fff_fallback
| tst RA, #HOOK_ACTIVE // Remember active hook before pcall.
| mov RB, BASE
@@ -1213,7 +1216,11 @@ static void build_subroutines(BuildCtx *ctx)
| b ->vm_call_dispatch
|
|.ffunc_2 xpcall
+ | ldr RB, L->maxstack
+ | add INS, BASE, NARGS8:RC
| ldrb RA, [DISPATCH, #DISPATCH_GL(hookmask)]
+ | cmp RB, INS
+ | blo ->fff_fallback
| checkfunc CARG4, ->fff_fallback // Traceback must be a function.
| mov RB, BASE
| strd CARG12, [BASE, #8] // Swap function and traceback.
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
@@ -1166,6 +1166,10 @@ static void build_subroutines(BuildCtx *ctx)
|//-- Base library: catch errors ----------------------------------------
|
|.ffunc pcall
+ | ldr TMP1, L->maxstack
+ | add TMP2, BASE, NARGS8:RC
+ | cmp TMP1, TMP2
+ | blo ->fff_fallback
| cmp NARGS8:RC, #8
| ldrb TMP0w, GL->hookmask
| blo ->fff_fallback
@@ -1185,6 +1189,10 @@ static void build_subroutines(BuildCtx *ctx)
| b ->vm_call_dispatch
|
|.ffunc xpcall
+ | ldr TMP1, L->maxstack
+ | add TMP2, BASE, NARGS8:RC
+ | cmp TMP1, TMP2
+ | blo ->fff_fallback
| ldp CARG1, CARG2, [BASE]
| ldrb TMP0w, GL->hookmask
| subs NARGS8:TMP1, NARGS8:RC, #16
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
@@ -1382,9 +1382,13 @@ static void build_subroutines(BuildCtx *ctx)
|//-- Base library: catch errors ----------------------------------------
|
|.ffunc pcall
+ | lw TMP1, L->maxstack
+ | addu TMP2, BASE, NARGS8:RC
| lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH)
| beqz NARGS8:RC, ->fff_fallback
- | move TMP2, BASE
+ |. sltu AT, TMP1, TMP2
+ | bnez AT, ->fff_fallback
+ |. move TMP2, BASE
| addiu BASE, BASE, 8
| // Remember active hook before pcall.
| srl TMP3, TMP3, HOOK_ACTIVE_SHIFT
@@ -1394,8 +1398,12 @@ static void build_subroutines(BuildCtx *ctx)
|. addiu NARGS8:RC, NARGS8:RC, -8
|
|.ffunc xpcall
+ | lw TMP1, L->maxstack
+ | addu TMP2, BASE, NARGS8:RC
| sltiu AT, NARGS8:RC, 16
| lw CARG4, 8+HI(BASE)
+ | sltu TMP1, TMP1, TMP2
+ | or AT, AT, TMP1
| bnez AT, ->fff_fallback
|. lw CARG3, 8+LO(BASE)
| lw CARG1, LO(BASE)
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)
| daddiu NARGS8:RC, NARGS8:RC, -8
- | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH)
| bltz NARGS8:RC, ->fff_fallback
|. move TMP2, BASE
| daddiu BASE, BASE, 16
@@ -1440,8 +1444,12 @@ static void build_subroutines(BuildCtx *ctx)
|. nop
|
|.ffunc xpcall
- | daddiu NARGS8:TMP0, NARGS8:RC, -16
- | 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)
+ | daddiu NARGS8:RC, NARGS8:RC, -16
| ld CARG2, 8(BASE)
| bltz NARGS8: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
@@ -1755,8 +1755,12 @@ static void build_subroutines(BuildCtx *ctx)
|//-- Base library: catch errors ----------------------------------------
|
|.ffunc pcall
+ | lwz TMP1, L->maxstack
+ | add TMP2, BASE, NARGS8:RC
| cmplwi NARGS8:RC, 8
| lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH)
+ | cmplw cr1, TMP1, TMP2
+ | cror 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
| blt ->fff_fallback
| mr TMP2, BASE
| la BASE, 8(BASE)
@@ -1767,14 +1771,19 @@ static void build_subroutines(BuildCtx *ctx)
| b ->vm_call_dispatch
|
|.ffunc xpcall
+ | lwz TMP1, L->maxstack
+ | add TMP2, BASE, NARGS8:RC
| cmplwi NARGS8:RC, 16
| lwz CARG3, 8(BASE)
+ | cmplw cr1, TMP1, TMP2
|.if FPU
| lfd FARG2, 8(BASE)
+ | cror 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
| lfd FARG1, 0(BASE)
|.else
| lwz CARG1, 0(BASE)
| lwz CARG2, 4(BASE)
+ | cror 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
| lwz CARG4, 12(BASE)
|.endif
| blt ->fff_fallback
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
@@ -1545,6 +1545,9 @@ static void build_subroutines(BuildCtx *ctx)
|//-- Base library: catch errors ----------------------------------------
|
|.ffunc_1 pcall
+ | mov L:RB, SAVE_L
+ | lea RA, [BASE+NARGS:RD*8]
+ | cmp RA, L:RB->maxstack; ja ->fff_fallback
| lea RA, [BASE+16]
| sub NARGS:RDd, 1
| mov PCd, 16+FRAME_PCALL
@@ -1563,6 +1566,9 @@ static void build_subroutines(BuildCtx *ctx)
| jmp ->vm_call_dispatch
|
|.ffunc_2 xpcall
+ | mov L:RB, SAVE_L
+ | lea RA, [BASE+NARGS:RD*8]
+ | cmp RA, L:RB->maxstack; ja ->fff_fallback
| mov LFUNC:RA, [BASE+8]
| checktp_nc LFUNC:RA, LJ_TFUNC, ->fff_fallback
| mov LFUNC:RB, [BASE] // Swap function and traceback.
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
@@ -1914,6 +1914,9 @@ static void build_subroutines(BuildCtx *ctx)
|//-- Base library: catch errors ----------------------------------------
|
|.ffunc_1 pcall
+ | mov L:RB, SAVE_L
+ | lea RA, [BASE+NARGS:RD*8]
+ | cmp RA, L:RB->maxstack; ja ->fff_fallback
| lea RA, [BASE+8]
| sub NARGS:RD, 1
| mov PC, 8+FRAME_PCALL
@@ -1925,6 +1928,9 @@ static void build_subroutines(BuildCtx *ctx)
| jmp ->vm_call_dispatch
|
|.ffunc_2 xpcall
+ | mov L:RB, SAVE_L
+ | lea RA, [BASE+NARGS:RD*8]
+ | cmp RA, L:RB->maxstack; ja ->fff_fallback
| cmp dword [BASE+12], LJ_TFUNC; jne ->fff_fallback
| mov RB, [BASE+4] // Swap function and traceback.
| mov [BASE+12], RB
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)
-- 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
+-- `pcall()`/xpcall()` triggered using metamethod `__call`.
+
+t = setmetatable({}, { __call = pcall })()
+
+test:ok(true, 'no stack overflow with metamethod __call')
+
+-- The testcase demonstrate a stack overflow in
+-- `pcall()`/`xpcall()` similar to the first testcase, but it is
+-- triggered using `unpack()`.
+
+t = {}
+local function f()
+ return pcall(unpack(t))
+end
+
+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, {}
+ coroutine.wrap(f)()
+end
+
+test:ok(true, 'no stack overflow with unpacked pcalls')
+
test:done(true)
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-12-10 7:25 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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
2025-12-10 7:23 ` [Tarantool-patches] [PATCH luajit 3/3][v2] Add stack check to pcall/xpcall Sergey Bronnikov via Tarantool-patches
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox