]> git.ipfire.org Git - thirdparty/zstd.git/commit
fix issue 44108 3033/head
authorYann Collet <cyan@fb.com>
Thu, 27 Jan 2022 13:13:45 +0000 (05:13 -0800)
committerYann Collet <cyan@fb.com>
Thu, 27 Jan 2022 13:49:59 +0000 (05:49 -0800)
commit8df1257c3cd70341307b87bffccbb334a10db5a1
tree1fbb52e923d753035c6dd94d6498211c100ca79d
parent7543085013db1a20a848d166e5931edc49e3cc2f
fix issue 44108

credit to oss-fuzz

In rare circumstances, the block-splitter might cut a block at the exact beginning of a repcode.
In which case, since litlength=0, if the repcode expected 1+ literals in front, its signification changes.
This scenario is controlled in ZSTD_seqStore_resolveOffCodes(),
and the repcode is transformed into a raw offset when its new meaning is incorrect.

In more complex scenarios, the previous block might be emitted as uncompressed after all,
thus modifying the expected repcode history.
In the case discovered by oss-fuzz, the first block is emitted as uncompressed,
so the repcode history remains at default values: 1,4,8.

But since the starting repcode is repcode3, and the literal length is == 0,
its meaning is : = repcode1 - 1.
Since repcode1==1, it results in an offset value of 0, which is invalid.

So that's what the `assert()` was verifying : the result of the repcode translation should be a valid offset.

But actually, it doesn't matter, because this result will then be compared to reality,
and since it's an invalid offset, it will necessarily be discarded if incorrect,
then the repcode will be replaced by a raw offset.

So the `assert()` is not useful.
Furthermore, it's incorrect, because it assumes this situation cannot happen, but it does, as described in above scenario.
lib/compress/zstd_compress.c