]> git.ipfire.org Git - thirdparty/zstd.git/commit
[zstdmt] Fix MSAN failure with ZSTD_p_forceWindow
authorNick Terrell <terrelln@fb.com>
Tue, 14 Feb 2017 02:27:34 +0000 (18:27 -0800)
committerNick Terrell <terrelln@fb.com>
Tue, 14 Feb 2017 03:11:22 +0000 (19:11 -0800)
commitecf90ca24b7031444133bc236a51683bd059dfc7
tree3660083ddd1686ac2a98e41fe551fd67ba22cef4
parentdb2666c10cb3953a38f153d011e3837da6312d83
[zstdmt] Fix MSAN failure with ZSTD_p_forceWindow

Reproduction steps:

```
make zstreamtest CC=clang CFLAGS="-O3 -g -fsanitize=memory -fsanitize-memory-track-origins"
./zstreamtest -vv -t4178 -i4178 -s4531
```

How to get to the error in gdb (may be a more efficient way):

* 2 breaks at zstd_compress.c:2418  -- in ZSTD_compressContinue_internal()
* 2 breaks at zstd_compress.c:2276  -- in ZSTD_compressBlock_internal()
* 1 break at zstd_compress.c:1547

Why the error occurred:

When `zc->forceWindow == 1`, after calling `ZSTD_loadDictionaryContent()` we
have `zc->loadedDictEnd == zc->nextToUpdate == 0`. But, we've really loaded up
to `iend` into the dictionary. Then in `ZSTD_compressBlock_internal()` we see
that `current > zc->nextToUpdate + 384`, so we load the last 192 bytes a second
time. In this case the bytes we are loading are a block of all 0s, starting in
the previous block. So when we are loading the last 192 bytes, we find a `match`
in the future, 183 bytes beyond `ip`. Since the block is all 0s, the match
extends to the end of the block. But in `ZSTD_count()` we only check that
`pIn < pInLoopLimit`, but since `pMatch > pIn`, `pMatch` eventually points past
the end of the buffer, causing the MSAN failure.

The fix:

The line changed sets sets `zc->nextToUpdate` to the end of the dictionary.
This is the behavior that existed before `ZSTD_p_forceWindow` was introduced.
This fixes the exposing test case. Since the code doesn't fail without
`zc->forceWindow`, it makes sense that this works. I've run the command
`./zstreamtest -T2mn` 64 times without failures. CI should also verify nothing
obvious broke.
lib/compress/zstd_compress.c