From d5bfb0a5c731e18b6b3776346efc595a6745358c Mon Sep 17 00:00:00 2001 From: Meo597 <197331664+Meo597@users.noreply.github.com> Date: Thu, 15 Oct 2026 10:54:43 +0800 Subject: [PATCH] lua: reduce binding setup and error redaction allocations --- common/lua/luar.go | 6 +++--- common/lua/program.go | 11 ++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/common/lua/luar.go b/common/lua/luar.go index 53a8f10b9..4ea4aeaf4 100644 --- a/common/lua/luar.go +++ b/common/lua/luar.go @@ -12,7 +12,7 @@ import ( // The returned function wraps slices without reflection or metatable lookup, // and pushes nil for nil slices. Use it with this state or its coroutines. func NewSlicePusher[T any](L *glua.LState) func(*glua.LState, []T) { - metatable := luar.New(L, []T{}).(*glua.LUserData).Metatable + metatable := luar.MT(L, []T(nil)).LTable return func(L *glua.LState, values []T) { if values == nil { L.Push(glua.LNil) @@ -60,11 +60,11 @@ func setSliceReadOnly[S ~[]E, E any](L *glua.LState, readOnly *glua.LFunction) { // A nil receiver lets AppendText return its argument as a writable []byte. methods := metatable.RawGetString("methods").(*glua.LTable) appendText := methods.RawGetString("AppendText") - methods.ForEach(func(key, method glua.LValue) { + for key, method := methods.Next(glua.LNil); key != glua.LNil; key, method = methods.Next(key) { if method == appendText { methods.RawSet(key, glua.LNil) } - }) + } visit(reflect.TypeFor[net.IPMask]()) } if element := typ.Elem(); element.Kind() == reflect.Slice { diff --git a/common/lua/program.go b/common/lua/program.go index b166829b7..da64ac220 100644 --- a/common/lua/program.go +++ b/common/lua/program.go @@ -165,7 +165,9 @@ func newSandboxedState() *glua.LState { // Redact addresses before caught errors become readable by the script. redactError := func(value glua.LValue) glua.LValue { if message, ok := value.(glua.LString); ok { - return glua.LString(redactMemoryAddresses(string(message))) + if redacted := redactMemoryAddresses(string(message)); redacted != string(message) { + return glua.LString(redacted) + } } return value } @@ -197,13 +199,13 @@ func newSandboxedState() *glua.LState { // Keep only time functions, including when os is accessed through require. osLib := L.GetGlobal(glua.OsLibName).(*glua.LTable) - osLib.ForEach(func(key, _ glua.LValue) { + for key, _ := osLib.Next(glua.LNil); key != glua.LNil; key, _ = osLib.Next(key) { switch key { case glua.LString("clock"), glua.LString("date"), glua.LString("difftime"), glua.LString("time"): default: osLib.RawSet(key, glua.LNil) } - }) + } // Prevent module injection through the global package table. module := L.GetGlobal(glua.LoadLibName).(*glua.LTable) @@ -230,6 +232,9 @@ func newSandboxedState() *glua.LState { var memoryAddressPattern = regexp.MustCompile(`0[xX][0-9a-fA-F]+`) func redactMemoryAddresses(message string) string { + if !strings.Contains(message, "0x") && !strings.Contains(message, "0X") { + return message + } return memoryAddressPattern.ReplaceAllString(message, "
") }