ZINFInflate wraps output on fill, never signals NOROOMZINFInflate (dog/git/ZINF.c) mishandles a too-small into slice: when
avail_out hits 0 it WRAPS next_out back to into[0] and keeps inflating
(corrupting already-produced bytes), then the trailing u8sFed(into, total_out)
— all-or-nothing — no-ops because total_out exceeds capacity, so the head never
advances and the call returns OK with produced 0. A genuine empty result also
yields 0, so overflow is undetectable by the caller. Surfaced by JS-035
(zip.inflate grow-and-retry), which had to add an XOR head-sentinel hack to
guess at overflow. Method: Issues.
avail_out == 0 reset block, dog/git/ZINF.c:31-34, inside the
inflate loop (lines 27-35); resets next_out/avail_out instead of erroring.into to the object's known uncompressed length
(keeper/UNPK.c:336,618, dog/git/PACK.c:177), so the wrap is LATENT there;
it only bites a caller that doesn't know the size up front.js/zip.cpp works around it with a head sentinel (into[0][0] ^=
0xa5, re-checked after the call) — that hack is deletable once this lands.PACKInflate (dog/git/PACK.c:171-182) never cross-checks
total_out == size, and UNPK.c:618 CONSUMES the inflated delta bytes.
Related: GIT-025 (PACKRecordEnd's measure-by-inflate needs the fix).into holds, return a NOROOM-style error
(new ZINFROOM) so the caller can grow and retry — never wrap or corrupt.OK, total_out equals the bytes actually present in into; the success
path stays byte-identical for the pre-sized native callers.dog/git libdog, ABC style; new code RON60-encoded, ZINF-prefixed
(abc/ok64), declared in ZINF.h beside ZINFFAIL/ZINFINIT/ZINFTOOBIG.OK).inflate returns Z_OK with avail_out == 0
(stream not ended, no room left) → inflateEnd(&zs); return ZINFROOM;.u8csUsed/u8sFed only on the Z_STREAM_END success path.keeper/test/ZINF.c case inflating a known stream into an
undersized into expects ZINFROOM (today: OK + produced 0 + corruption).ZINFROOM to ZINF.h; fix the loop in ZINF.c; ctest green across
ZINF/PACK/UNPK (the pre-sized callers must stay green).PACKInflate: a lying size header (stream inflates past size) must
surface as PACKBADOBJ (total_out == size check), not silent corruption.zip.cpp:46-55): drop the XOR hack, grow directly on a ZINFROOM throw.ZINF.c avail_out==0 reset) and ZINF.h declares no ZINFROOM.