mirror of
https://github.com/google/brotli.git
synced 2026-07-08 17:56:58 +00:00
Potential bug with bad dictionary transform ? #275
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @OlivierNV on GitHub (Mar 21, 2019).
It seems that the format would allow a dictionary transform that removes the first or last characters of a dictionary word such that the resulting word size has zero length.
This could also be combined with a custom distance table with a single zero-bit symbol such that the state machine hangs reading zero bits from the bitstream and producing zero bytes.
Would it make sense to update the specification to make it illegal to have a dictionary transform that results in a word length smaller than 2 ?
@eustas commented on GitHub (Mar 22, 2019):
This might be a useful addition to "Shared Brotli" spec.
If it is a real bug, then there will be no choice, but to update RFC, but otherwise, it is better to leave it untouched.
I'll try to describe, why this situation (infinite loop) is impossible. Would be very grateful, if you double-check.
0distance code (use last distance) has very limited ability to reference to static dictionary, because distances that refer to dictionary are not stored in distance ringbuffertestIntactDistanceRingBuffertestsIn "Shared Brotli" shift might be smaller and transform table is different -> this bug might become possible to exploit.
@eustas commented on GitHub (Mar 22, 2019):
+@lvandeve
@OlivierNV commented on GitHub (Mar 22, 2019):
Ah, did not realize that distances that refer to dictionary were not stored in ring buffer: in this case, yes, it would be difficult to produce a non-zero transform_idx without consuming any bits.
@lvandeve commented on GitHub (Mar 22, 2019):
Thanks for pointing out this very interesting detail :)
Indeed the amount of symbols read while decoding commands is bounded, even if of zero length, which can be seen in "10. Decoding Algorithm" in the specification:
https://tools.ietf.org/rfc/rfc7932.txt
@OlivierNV commented on GitHub (Mar 22, 2019):
Hmm. Actually, the distance ring buffer is persistent across meta-blocks, so it's possible to start a block with any arbitrary distance in the ring buffer, so the only thing necessary to exploit this would be an alphabet size of 1 such that only one command can be encoded using zero bits (zero insert length with dictionary copy using distance from ring buffer)
@eustas commented on GitHub (Mar 22, 2019):
Yes, distance ring buffer persists, but distance to dictionary (max [backward] distance) persists as well. So, as I mentioned earlier, it is impossible to put distance that refers to dictionary in distance ring buffer (except for initial 4).
@OlivierNV commented on GitHub (Mar 22, 2019):
Oh I see, the maximum distance value in the ring buffer is always a non-dictionary distance, so it's not possible to produce a dictionary transform distance code that would not require extra bits...
Regarding the bound for the amount of symbols being read per meta-block, the 16M bound is based on the assumption that at least one byte is produced by every command being read (with meta block length being limited to 16M).