PACKRecordEnd carves obj.size straight off the wire — unbounded scratchPACKRecordEnd (dog/git/PACK.c:184-202) measures a record's extent by
inflating it into BASS scratch sized a_carve(u8, sc, obj.size) — and
obj.size is the record's own untrusted varint, up to ~2^60. One corrupt
or hostile record demands an arbitrary carve: OOM/DoS at every scan site
(PIDXScan per record, the js binding via GIT-007). Found in the
2026-07-24 dog/git review. Method: work.
dog/git/PACK.c:197 — a_carve(u8, sc, obj.size ? obj.size : 1);
the varint decoder (PACKDrainVarint) happily yields huge sizes.(packlen - offset) * 1032 — anything
above that is corruption by construction, rejectable BEFORE carving.ZINFInflate output-wrap is what
makes "inflate into a too-small buffer" survivable-but-corrupting;
once GIT-011 lands a NOROOM error, a chunked measure loop (fixed
small carve, count total_out) becomes the clean way to size-check.dog/git libdog, ABC style; BASS carve rules (abc.mkd §BASS) — the
carve stays in the op's own frame.PIDXScan / keeper scan callers and their tests stay green.test(obj.size <= (packlen - offset) * 1032ULL,
PACKBADFMT) before the carve (watch the multiply overflow — clamp
first). The chunked-measure rewrite can ride with GIT-011.dog/test/ (absurd declared size → bounded error).//GIT-025 on base 06a2a21d
(orchestrator-verified, not landed). git/PACK.c pre-carve bound
(obj.size <= left * PACK_ZLIB_MAX_RATIO, clamped multiply),
git/PACK.h PACK_ZLIB_MAX_RATIO 1032, new test/PACKEND.c
(honest_walk / absurd_size / plausible_lie / within_ratio) +
CMake row. ctest 77/77 green.GIT-025: bound declared record size before carving