codec: bound value-decode recursion to prevent stack overflow

Apply recursion limit to decoding

Adds a testxcode regression that decodes a long run of 0x82 and asserts
the decode faults instead of recursing without bound.
This commit is contained in:
Sang Woo Kim authored and Michael Davidsaver committed 2026-06-01 17:11:28 -07:00
1 parent 731fb27f13
commit 1679799691
3 files changed
+41 -15

No files matched your search

+21 -1
View File
@@ -1176,6 +1176,25 @@ void testRegressBadBitMask()
}
}
// A run of TypeCode::Any (0x82) leaf bytes encodes an Any value whose content is
// itself an Any, repeated. The value decoder must be bounded by its depth guard
// and fault, instead of recursing once per byte (from_wire_field -> from_wire_full
// -> from_wire_field -> ...) and exhausting the thread stack. Reaching the
// assertion at all is the regression: without the bound this overflows the stack
// and crashes the process (SIGSEGV is not a std::exception, so it is uncatchable).
void testRegressDeepAny()
{
testDiag("%s", __func__);
std::vector<uint8_t> msg(1000000u, 0x82u); // 0x82 == TypeCode::Any
TypeStore ctxt;
Value val;
FixedBuf buf(false, msg);
from_wire_type_value(buf, ctxt, val);
testFalse(buf.good())<<" deeply-nested Any must fault, not recurse without bound";
}
// test the common case for a pvRequest of caching an empty Struct
void testEmptyRequest()
{
@@ -1256,7 +1275,7 @@ void testPartialXCode()
MAIN(testxcode)
{
testPlan(150);
testPlan(151);
testSetup();
testDeserializeString();
testSerialize1();
@@ -1272,6 +1291,7 @@ MAIN(testxcode)
testRegressRedundantBitMask();
testRegressCNEN();
testRegressBadBitMask();
testRegressDeepAny();
testBadFieldName();
testEmptyRequest();
testPartialXCode();