Problem
The encoder currently has two correctness holes that can crash the process:
1. Circular reference — infinite recursion / stack overflow
encode_plain_table and encode_lazy_object_walking carry no visited-set. A self-referential table causes unconditional infinite recursion:
local t = {}
t.self = t
qjson.encode(t) -- stack overflow, not a clean error()
lua-cjson raises a Lua error at the configured encode_max_depth (default 1000). qjson has no guard at all on the encode path — only the parse path enforces max_depth.
2. Encode depth — no limit enforced
Deeply-nested tables (not necessarily circular) can also exhaust the stack. There is no depth counter in any of the four encode helpers (encode_array, encode_object, encode_lazy_object_walking, encode_lazy_array_walking).
Fix scope
- Add a depth counter (thread-upvalue or passed argument) to all four encode helpers.
- On depth > limit, raise
"qjson.encode: max depth exceeded".
- Default limit: 1000 (matching lua-cjson).
- Add Lua-level tests for both cases: circular ref and deep-nest.
Affected files
lua/qjson/table.lua — all four encode helpers
tests/lua/ — new test cases
Priority
P0 — process crash, no workaround for callers.
Problem
The encoder currently has two correctness holes that can crash the process:
1. Circular reference — infinite recursion / stack overflow
encode_plain_tableandencode_lazy_object_walkingcarry no visited-set. A self-referential table causes unconditional infinite recursion:lua-cjson raises a Lua error at the configured
encode_max_depth(default 1000). qjson has no guard at all on the encode path — only the parse path enforcesmax_depth.2. Encode depth — no limit enforced
Deeply-nested tables (not necessarily circular) can also exhaust the stack. There is no depth counter in any of the four encode helpers (
encode_array,encode_object,encode_lazy_object_walking,encode_lazy_array_walking).Fix scope
"qjson.encode: max depth exceeded".Affected files
lua/qjson/table.lua— all four encode helperstests/lua/— new test casesPriority
P0 — process crash, no workaround for callers.