Skip to content

Harden the zip cache read path against a corrupt X-Size - #493

Merged
xroche merged 1 commit into
masterfrom
p2-4-reland
Jul 5, 2026
Merged

Harden the zip cache read path against a corrupt X-Size#493
xroche merged 1 commit into
masterfrom
p2-4-reland

Conversation

@xroche

@xroche xroche commented Jul 5, 2026

Copy link
Copy Markdown
Owner

A tampered X-Size in a zip cache entry wrapped into an oversized malloc (an allocation-size-too-big abort under ASan). The alloc casts to int, so besides a negative size, any positive value at or above INT_MAX truncates negative and wraps too; reject the whole out-of-range span before the load. -#test=cache-corrupt byte-injects a real cache (bad/oversized/negative X-Size, blanked X-In-Cache, smashed header, garbled deflate) and checks each entry is rejected in-session without tainting its sibling.

Only the live zip cache format is covered; the legacy .dat format is dead and slated for removal. This re-lands the change that was orphaned when #492 merged into its stacked base branch instead of master.

A tampered X-Size in a zip cache entry wrapped into an oversized malloc
(an allocation-size-too-big abort under ASan). The alloc casts to int
(malloct((int) r.size + 1)), so besides a negative size, any positive
value at or above INT_MAX truncates negative and wraps too; reject the
whole out-of-range span before the load.

-#test=cache-corrupt byte-injects a real two-entry zip (bad/oversized/
negative X-Size, blanked X-In-Cache, smashed local header, garbled
deflate) and checks each entry degrades to STATUSCODE_INVALID in the same
read session as its intact sibling, so one corrupt entry never taints the
cache. Only the live zip format is covered; the legacy .dat reader is dead
and slated for removal.

Re-lands the change orphaned when it was merged into its stacked base
branch instead of master.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
@xroche
xroche merged commit abaf9b6 into master Jul 5, 2026
15 checks passed
xroche added a commit that referenced this pull request Jul 5, 2026
* X-Size hardening rejected legit headers-only >2GB cache entries

The guard from #493 bounds X-Size to [0, INT_MAX) before the header/data
split, but a headers-only entry (X-In-Cache: 0) legitimately exceeds
INT_MAX: every >2GB non-html file is stored that way, so updates
invalidated the entry and re-fetched the file. Keep the negative check
global, gate the INT_MAX half on data-in-cache (the write path asserts
those fit an int), and reject oversized entries at the one remaining
int-sized in-memory read.

-#test=cache-corrupt gains a headers-only fixture: a forged >INT_MAX
X-Size must survive a header probe with the size intact (fails on the
old code) while an in-memory read of the same entry still degrades.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>

* review: pin the INT_MAX boundary and the headers-only negative X-Size

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>

---------

Signed-off-by: Xavier Roche <roche@httrack.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@xroche
xroche deleted the p2-4-reland branch July 27, 2026 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant