Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix corruption that rarely occurs in 32-bit mode with wlog=25 #3361

Merged
merged 1 commit into from
Dec 15, 2022

Conversation

terrelln
Copy link
Contributor

Fix an off-by-one error in the compressor that emits corrupt blocks if:

  • Zstd is compiled in 32-bit mode
  • The windowLog == 25 exactly
  • An offset of 2^25-3, 2^25-2, 2^25-1, or 2^25 is emitted
  • The bitstream had 7 bits leftover before writing the offset

This bug has been present since before v1.0, but wasn't able to easily be triggered, since until somewhat recently zstd wasn't able to find matches that were within 128KB of the window size.

Add a test case, and fix 2 bugs in ZSTD_compressSequences():

  • The ZSTD_isRLE() check was incorrect. It wouldn't produce corruption, but it could waste CPU and not emit RLE even if the block was RLE
  • One windowSize was 1 << windowLog, not 1u << windowLog

Thanks to @tansy for finding the issue, and giving us a reproducer!

Fixes Issue #3350.

@terrelln
Copy link
Contributor Author

A follow up is to add fuzzers that could catch this issue:

  1. Run our fuzzers in 32-bit mode in OSS-Fuzz
  2. Add a fuzzer which uses the ZSTD_compressSequences() API to generate valid fuzzed sequences, and check that they round trip. This would allow us to fuzz very large offsets without requiring the fuzzer generate many many MB of input data.

@@ -6256,7 +6256,7 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,

if (!cctx->isFirstBlock &&
ZSTD_maybeRLE(&cctx->seqStore) &&
ZSTD_isRLE((BYTE const*)src, srcSize)) {
ZSTD_isRLE(ip, blockSize)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch !

Fix an off-by-one error in the compressor that emits corrupt blocks if:

* Zstd is compiled in 32-bit mode
* The windowLog == 25 exactly
* An offset of 2^25-3, 2^25-2, 2^25-1, or 2^25 is emitted
* The bitstream had 7 bits leftover before writing the offset

This bug has been present since before v1.0, but wasn't able to easily
be triggered, since until somewhat recently zstd wasn't able to find
matches that were within 128KB of the window size.

Add a test case, and fix 2 bugs in `ZSTD_compressSequences()`:
* The `ZSTD_isRLE()` check was incorrect. It wouldn't produce
  corruption, but it could waste CPU and not emit RLE even if the block
  was RLE
* One windowSize was `1 << windowLog`, not `1u << windowLog`

Thanks to @tansy for finding the issue, and giving us a reproducer!

Fixes Issue facebook#3350.
@terrelln terrelln merged commit a91e7ec into facebook:dev Dec 15, 2022
daniellerozenblit added a commit to daniellerozenblit/oss-fuzz that referenced this pull request Jan 20, 2023
We'd like to enable 32-bit mode fuzz tests for zstd for portability and to catch bugs such as this one (facebook/zstd#3361) that only occur when built in 32-bit mode.

Is there anything else that needs to be done to enable 32-bit fuzzing for zstd?
daniellerozenblit added a commit to daniellerozenblit/oss-fuzz that referenced this pull request Jan 24, 2023
We would like to extend zstd fuzzing to 32-bit in order to ensure the portability of zstd and find bugs (such as facebook/zstd#3361) that only occur on 32-bit platforms.
DavidKorczynski pushed a commit to google/oss-fuzz that referenced this pull request Jan 25, 2023
We would like to extend zstd fuzzing to 32-bit in order to further
ensure that zstd is portable and to find bugs (such as
facebook/zstd#3361) that only occur on 32-bit
platforms.
@Cyan4973 Cyan4973 mentioned this pull request Feb 9, 2023
eamonnmcmanus pushed a commit to eamonnmcmanus/oss-fuzz that referenced this pull request Mar 15, 2023
We would like to extend zstd fuzzing to 32-bit in order to further
ensure that zstd is portable and to find bugs (such as
facebook/zstd#3361) that only occur on 32-bit
platforms.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants