From affd4e432ee299d22be95314bcc72a9347f586fb Mon Sep 17 00:00:00 2001 From: Thierry Fournier Date: Wed, 26 Feb 2025 10:24:52 +0100 Subject: [PATCH] fix: stack overflow in table.concat function The previous implementation of tableConcat was pushing all values and separators onto the Lua stack before concatenating them, which caused stack overflow with large tables. This fix changes the implementation to build the result string incrementally rather than pushing all values onto the stack first, preventing stack overflow with large tables. Example that would previously fail but now works correctly: ``` package main import "github.com/yuin/gopher-lua" func main() { var L *lua.LState var err error L = lua.NewState() defer L.Close() err = L.DoString(` local t = {} for i = 1, 10000 do t[i] = tostring(i) end local s = table.concat(t, ',') `) if err != nil { println(err.Error()) } } ``` --- tablelib.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tablelib.go b/tablelib.go index f3f46070..02474311 100644 --- a/tablelib.go +++ b/tablelib.go @@ -66,19 +66,18 @@ func tableConcat(L *LState) int { L.Push(emptyLString) return 1 } - //TODO should flushing? - retbottom := L.GetTop() + result := "" for ; i <= j; i++ { v := tbl.RawGetInt(i) if !LVCanConvToString(v) { L.RaiseError("invalid value (%s) at index %d in table for concat", v.Type().String(), i) } - L.Push(v) + result += LVAsString(v) if i != j { - L.Push(sep) + result += LVAsString(sep) } } - L.Push(stringConcat(L, L.GetTop()-retbottom, L.reg.Top()-1)) + L.Push(LString(result)) return 1 }