From 0ad0d5fa0b8e9909c83abda941cb4151f8c3942f Mon Sep 17 00:00:00 2001 From: Iyaz Shaikh Date: Wed, 7 Oct 2026 09:11:51 -0400 Subject: [PATCH] Skip frame register clearing when a call has extra arguments When a caller passes more arguments than the callee has registers, l.top is past ci.top and the clear added in #145 panics on a backwards slice. The extra arguments are already discarded when l.top is reset to ci.top. Co-Authored-By: Claude Opus 5.5 --- security_test.go | 7 +++++++ stack.go | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/security_test.go b/security_test.go index a1741f3..8d4c232 100644 --- a/security_test.go +++ b/security_test.go @@ -170,6 +170,13 @@ func TestCraftedReturnDoesNotExposePoppedHostValues(t *testing.T) { } } +func TestCallWithMoreArgumentsThanRegisters(t *testing.T) { + l := NewState() + if err := DoString(l, `local function noop() end noop(nil, "x", {})`); err != nil { + t.Fatal(err) + } +} + func TestDebugGetHookWithoutExternalHook(t *testing.T) { l := NewState() Require(l, "debug", DebugOpen, true) diff --git a/stack.go b/stack.go index 9ba15b8..2616638 100644 --- a/stack.go +++ b/stack.go @@ -187,7 +187,9 @@ func (l *State) pushLuaFrame(function, base, resultCount int, p *prototype) *cal if l.top > first { first = l.top } - clear(l.stack[first:ci.top]) + if first < ci.top { + clear(l.stack[first:ci.top]) + } l.callInfo = ci l.top = ci.top return ci