A malformed archive could drive several out-of-bounds accesses in the
decoder, all reachable from untrusted input:
- ht_dec() expanded a Huffman RepeatCode without checking the
destination against the end of the local stream[] array, so a crafted
tree wrote past it on the stack. Reject the overrun as UC2_Damaged.
- The LZ match copy in both the rANS and the Huffman paths used a match
distance straight from the bitstream. A distance larger than the
bytes written so far (or one wrapped huge by a short bits_get on the
distance extra-bits) made (u16)(tail - dist) reference window bytes
that were never written, copying uninitialised memory into the
output. Track produced history (master fill + output, saturating at
the 64KB window) and reject dist beyond it.
- struct delta carried val[8], but decompressor() accepts methods up to
49, giving strides up to 10; strides 9 and 10 indexed past the array
(and silently mis-decoded). Size val[] to cover the accepted range.
Found by a code-review pass. Valid round-trips are unchanged: 22/22
ctest on Release and ASan, plus ASan round-trips across all levels for
inputs spanning the 64KB window. The assemble_name NULL-deref raised in
the same review is not reachable (dos_name is a fixed 11 bytes, far
under the 300-byte name buffer), so it is left as-is.