Skip to content

THRIFT-6049: Limit struct read/write recursion depth in Lua library#3554

Open
Jens-G wants to merge 1 commit into
apache:masterfrom
Jens-G:lua-recursion-depth
Open

THRIFT-6049: Limit struct read/write recursion depth in Lua library#3554
Jens-G wants to merge 1 commit into
apache:masterfrom
Jens-G:lua-recursion-depth

Conversation

@Jens-G
Copy link
Copy Markdown
Member

@Jens-G Jens-G commented May 28, 2026

THRIFT-6049: Limit struct read/write recursion depth in the Lua library

Change

The Lua generator wraps each generated read()/write() body with incrementRecursionDepth() / pcall / decrementRecursionDepth() on TProtocolBase (limit DEFAULT_RECURSION_DEPTH = 64, TProtocolException.DEPTH_LIMIT on excess). Previously only skip() was bounded. Unions and exceptions are generated through the same path, so they are bounded too.

Test

Replaces the isolated counter test with a generated-code round-trip (lib/lua/test/test_recursion_depth.lua) over a recursive struct (RecTree), union (RecUnion) and exception (RecError) from a new RecursionDepth.thrift, driven through the generated read()/write() on a real TBinaryProtocol. For each of the three kinds:

  • a chain at the limit round-trips (also proving the guard does not double-count — a chain of 64 would be rejected at 32 otherwise);
  • a chain past the limit is rejected on write;
  • a hand-serialized over-limit payload is rejected on read, crafted with the real recursive field (id 1 = list<self>) so the reader recurses through the guarded path rather than the separate, unbounded skip().

Validated locally with Lua 5.4: 21/21 pass. No functional Lua CI (--without-lua); the only CI surface touched is the C++ compiler build (generator edit). skip() stays separately bounded.

🤖 Generated with Claude Code

@Jens-G Jens-G requested review from fishy and mhlakhani as code owners May 28, 2026 11:46
@mergeable mergeable Bot added lua Pull requests that update Lua code compiler labels May 28, 2026
@Jens-G Jens-G marked this pull request as draft May 28, 2026 22:45
@Jens-G Jens-G force-pushed the lua-recursion-depth branch from bca5d0d to 11920a3 Compare May 31, 2026 12:16
@Jens-G Jens-G marked this pull request as ready for review May 31, 2026 12:21
@Jens-G Jens-G force-pushed the lua-recursion-depth branch from 11920a3 to 351cf16 Compare May 31, 2026 12:25
Client: lua

The Lua generator wraps each generated read()/write() body with
incrementRecursionDepth()/pcall/decrementRecursionDepth() on TProtocolBase
(limit DEFAULT_RECURSION_DEPTH = 64, TProtocolException.DEPTH_LIMIT on
excess). Previously only skip() was bounded, so the generated read/write
path recursed without limit. Unions and exceptions are generated through the
same path, so they are bounded too.

Replace the isolated counter test with a generated-code round-trip
(lib/lua/test/test_recursion_depth.lua) over a recursive struct (RecTree),
union (RecUnion) and exception (RecError) from a new RecursionDepth.thrift,
driven through the generated read()/write() over a real TBinaryProtocol: a
chain at the limit round-trips (also proving the guard does not double-count),
a chain past it is rejected on write, and a hand-serialized over-limit payload
is rejected on read (crafted with the real recursive field, id 1 = list<self>,
so the reader recurses through the guarded path rather than the separate,
unbounded skip()).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Jens-G Jens-G force-pushed the lua-recursion-depth branch from 351cf16 to 07e7c38 Compare June 1, 2026 18:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

compiler lua Pull requests that update Lua code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant