Skip to content

Commit 25d81b9

Browse files
committed
Better distinguish the 'kind' of VM interrupt we're invoking
1 parent 06ad444 commit 25d81b9

File tree

10 files changed

+40
-17
lines changed

10 files changed

+40
-17
lines changed

VM/include/lua.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,18 @@ enum lua_Type
135135
// the count of TValue type tags
136136
LUA_T_COUNT = LUA_TPROTO
137137
};
138+
139+
// ServerLua: so we can figure out _why_ an interrupt happened to track
140+
// whether the trail of interrupts is what we'd expect.
141+
enum lua_InterruptReason
142+
{
143+
LUA_INTERRUPT_NORMAL = -1,
144+
LUA_INTERRUPT_EVENTS = -2,
145+
LUA_INTERRUPT_LLLIB = -3,
146+
LUA_INTERRUPT_STDLIB = -4,
147+
LUA_INTERRUPT_METAMETHOD = -5,
148+
LUA_INTERRUPT_CALLTAIL = -6,
149+
};
138150
// clang-format on
139151

140152
// type of numbers in Luau

VM/src/cjson/lua_cjson.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
883883
if (luaL_getmetafield(l, -1, "__tojson")) {
884884
lua_pushvalue(l, -2);
885885
// ServerLua: Check for interrupt to allow pre-emptive abort before calling metamethod
886-
luau_callinterrupthandler(l, -3);
886+
luau_callinterrupthandler(l, LUA_INTERRUPT_LLLIB);
887887
lua_call(l, 1, 1);
888888
json_append_data(l, cfg, current_depth, json);
889889
// Remove the original object
@@ -893,7 +893,7 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
893893
if (luaL_getmetafield(l, -1, "__len")) {
894894
lua_pushvalue(l, -2);
895895
// ServerLua: Check for interrupt to allow pre-emptive abort before calling metamethod
896-
luau_callinterrupthandler(l, -3);
896+
luau_callinterrupthandler(l, LUA_INTERRUPT_LLLIB);
897897
lua_call(l, 1, 1);
898898
len = lua_tonumber(l, -1);
899899
lua_pop(l, 1);

VM/src/laux.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ int luaL_callmeta(lua_State* L, int obj, const char* event)
280280
return 0;
281281
lua_pushvalue(L, obj);
282282
// ServerLua: Check for interrupt to allow pre-emptive abort before calling metamethod
283-
luau_callinterrupthandler(L, -3);
283+
luau_callinterrupthandler(L, LUA_INTERRUPT_METAMETHOD);
284284
lua_call(L, 1, 1);
285285
return 1;
286286
}

VM/src/lllevents.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ int llevents_handle_event_cont(lua_State *L, int status)
607607
// Check for interrupts between handlers to prevent abuse
608608
if (LUAU_LIKELY(!!interrupt))
609609
{
610-
interrupt(L, -2); // -2 indicates "handler interrupt check"
610+
interrupt(L, LUA_INTERRUPT_EVENTS);
611611
if (L->status != LUA_OK)
612612
return -1;
613613
}

VM/src/llltimers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ static int lltimers_tick_cont(lua_State *L, [[maybe_unused]]int status)
672672
// Check for interrupts between timers to prevent abuse
673673
if (LUAU_LIKELY(!!interrupt))
674674
{
675-
interrupt(L, -2); // -2 indicates "handler interrupt check"
675+
interrupt(L, LUA_INTERRUPT_EVENTS);
676676
if (L->status != LUA_OK)
677677
return -1;
678678
}

VM/src/lstrlib.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,8 @@ static const char* match(MatchState* ms, const char* s, const char* p)
438438
{
439439
// this interrupt is not yieldable
440440
L->nCcalls++;
441-
interrupt(L, -1);
441+
// ServerLua: blame this directly.
442+
interrupt(L, LUA_INTERRUPT_STDLIB);
442443
L->nCcalls--;
443444
}
444445

@@ -809,7 +810,7 @@ static void add_value(MatchState* ms, luaL_Strbuf* b, const char* s, const char*
809810
lua_pushvalue(L, 3);
810811
n = push_captures(ms, s, e);
811812
// ServerLua: Check for interrupt to allow pre-emptive abort before calling replacement function
812-
luau_callinterrupthandler(L, -4);
813+
luau_callinterrupthandler(L, LUA_INTERRUPT_STDLIB);
813814
lua_call(L, n, 1);
814815
break;
815816
}

VM/src/ltablib.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ static int foreachi(lua_State* L)
2525
lua_pushinteger(L, i); // 1st argument
2626
lua_rawgeti(L, 1, i); // 2nd argument
2727
// ServerLua: Check for interrupt to allow pre-emptive abort before calling user iterator function
28-
luau_callinterrupthandler(L, -4);
28+
luau_callinterrupthandler(L, LUA_INTERRUPT_STDLIB);
2929
lua_call(L, 2, 1);
3030
if (!lua_isnil(L, -1))
3131
return 1;
@@ -45,7 +45,7 @@ static int foreach (lua_State* L)
4545
lua_pushvalue(L, -3); // key
4646
lua_pushvalue(L, -3); // value
4747
// ServerLua: Check for interrupt to allow pre-emptive abort before calling user iterator function
48-
luau_callinterrupthandler(L, -4);
48+
luau_callinterrupthandler(L, LUA_INTERRUPT_STDLIB);
4949
lua_call(L, 2, 1);
5050
if (!lua_isnil(L, -1))
5151
return 1;
@@ -334,7 +334,7 @@ static int sort_func(lua_State* L, const TValue* l, const TValue* r)
334334
setobj2s(L, L->top + 2, r);
335335
L->top += 3; // safe because of LUA_MINSTACK guarantee
336336
// ServerLua: Check for interrupt to allow pre-emptive abort before calling user comparison function
337-
luau_callinterrupthandler(L, -4);
337+
luau_callinterrupthandler(L, LUA_INTERRUPT_STDLIB);
338338
luaD_call(L, L->top - 3, 1);
339339
L->top -= 1; // maintain stack depth
340340

VM/src/lvmexecute.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,15 @@
7777
#define VM_PATCH_C(pc, slot) *const_cast<Instruction*>(pc) = ((uint8_t(slot) << 24) | (0x00ffffffu & *(pc)))
7878
#define VM_PATCH_E(pc, slot) *const_cast<Instruction*>(pc) = ((uint32_t(slot) << 8) | (0x000000ffu & *(pc)))
7979

80-
#define VM_INTERRUPT() \
80+
// ServerLua: Allow interrupting with different codes.
81+
#define VM_INTERRUPT() VM_INTERRUPT_WITHCODE(LUA_INTERRUPT_NORMAL)
82+
#define VM_INTERRUPT_WITHCODE(code) \
8183
{ \
8284
void (*interrupt)(lua_State*, int) = L->global->cb.interrupt; \
8385
if (LUAU_UNLIKELY(!!interrupt)) \
8486
{ /* the interrupt hook is called right before we advance pc */ \
85-
VM_PROTECT(L->ci->savedpc++; interrupt(L, -1)); \
87+
static_assert((code) < 0, "code is negative"); \
88+
VM_PROTECT(L->ci->savedpc++; interrupt(L, (code))); \
8689
if (L->status != 0) \
8790
{ \
8891
L->ci->savedpc--; \
@@ -1102,7 +1105,7 @@ static void luau_execute(lua_State* L)
11021105
// We're not doing this because the interrupt might fail, we're doing this because
11031106
// we need to remember that we're _past_ the LOP_CALL if we interrupt.
11041107
VM_PROTECT_PC();
1105-
VM_INTERRUPT();
1108+
VM_INTERRUPT_WITHCODE(LUA_INTERRUPT_CALLTAIL);
11061109
L->global->calltailinterruptcheck = 0;
11071110
}
11081111

VM/src/lvmutils.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ static StkId callTMres(lua_State* L, StkId res, const TValue* f, const TValue* p
7474
luaD_checkstack(L, 3);
7575
L->top += 3;
7676
// ServerLua: Check for interrupt to allow pre-emptive abort before calling metamethod
77-
luau_callinterrupthandler(L, -3);
77+
luau_callinterrupthandler(L, LUA_INTERRUPT_METAMETHOD);
7878
luaD_call(L, L->top - 3, 1);
7979
res = restorestack(L, result);
8080
L->top--;
@@ -99,7 +99,7 @@ static void callTM(lua_State* L, const TValue* f, const TValue* p1, const TValue
9999
luaD_checkstack(L, 4);
100100
L->top += 4;
101101
// ServerLua: Check for interrupt to allow pre-emptive abort before calling metamethod
102-
luau_callinterrupthandler(L, -3);
102+
luau_callinterrupthandler(L, LUA_INTERRUPT_METAMETHOD);
103103
luaD_call(L, L->top - 4, 0);
104104
}
105105

@@ -620,7 +620,7 @@ LUAU_NOINLINE void luaV_callTM(lua_State* L, int nparams, int res)
620620
LUAU_ASSERT(L->top == L->base + nparams);
621621

622622
// ServerLua: Check for interrupt to allow pre-emptive abort before calling C function metamethod
623-
luau_callinterrupthandler(L, -3);
623+
luau_callinterrupthandler(L, LUA_INTERRUPT_METAMETHOD);
624624

625625
lua_CFunction func = clvalue(fun)->c.f;
626626
int n = func(L);

tests/SLConformance.test.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -908,8 +908,15 @@ TEST_CASE("Metamethods and library callbacks receive interrupt checks")
908908
runConformance("metamethod_and_callback_interrupts.lua", nullptr, [](lua_State* L) {
909909
// Set up interrupt handler that clears the flag for metamethod (-3) and library callback (-4) interrupts
910910
lua_callbacks(L)->interrupt = [](lua_State* L, int gc) {
911-
if (gc != -3 && gc != -4)
911+
switch(gc)
912+
{
913+
case LUA_INTERRUPT_METAMETHOD:
914+
case LUA_INTERRUPT_LLLIB:
915+
case LUA_INTERRUPT_STDLIB:
916+
break;
917+
default:
912918
return;
919+
}
913920

914921
RuntimeState* state = (RuntimeState*)L->userdata;
915922
state->interrupt_should_clear = false;

0 commit comments

Comments
 (0)