fix(script): bound how deep json.encode walks a Lua table

This commit is contained in:
aykhans committed 2026-10-01 22:13:29 +04:00
1 parent 847c4b39ce
commit cd0fa453c2
2 files changed
+12

No files matched your search

+11
View File
@@ -45,9 +45,14 @@ func luaJSONDecode(state *lua.LState) int {
return 1
}
// luaJSONMaxDepth matches the depth encoding/json accepts, so a table a script
// decoded always encodes again, and it stays far below what overflows the Go stack.
const luaJSONMaxDepth = 10000
// luaToGo converts a Lua value to a JSON-encodable Go value.
// It can return the following errors:
// - types.ErrScriptJSONCycle
// - types.ErrScriptJSONDepth
// - types.ScriptTypeError
func luaToGo(value lua.LValue, visiting map[*lua.LTable]bool) (any, error) {
switch v := value.(type) {
@@ -63,6 +68,12 @@ func luaToGo(value lua.LValue, visiting map[*lua.LTable]bool) (any, error) {
if visiting[v] {
return nil, types.ErrScriptJSONCycle
}
// visiting holds the tables on the current path, so its size is the depth.
// A table millions of levels deep overflows the Go stack, which is a fatal
// error no pcall can catch, so the descent is bounded well before that.
if len(visiting) >= luaJSONMaxDepth {
return nil, types.ErrScriptJSONDepth
}
visiting[v] = true
defer delete(visiting, v)
+1
View File
@@ -442,6 +442,7 @@ var (
ErrScriptHTTPURLInvalid = errors.New("URL must be an absolute http or https URL")
ErrScriptHTTPUnknownOption = errors.New("unknown option")
ErrScriptJSONCycle = errors.New("cannot encode a table that contains itself")
ErrScriptJSONDepth = errors.New("cannot encode a table nested too deeply")
)
type ScriptTypeError struct {