diff options
author | Hans Wennborg <hans@chromium.org> | 2024-02-22 07:01:51 +0000 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2024-02-21 23:08:18 -0800 |
commit | 74a1c5030338acadbbfb32609774a974be89007f (patch) | |
tree | 1b79a7bf87717df9198e092ce12d68f0cc9bf6a1 | |
parent | 03c356e4c106e4e6850edaae29be45290a2cb36c (diff) | |
download | zlib-74a1c5030338acadbbfb32609774a974be89007f.tar.gz |
[zlib] Increase the coverage of deflate_fuzzer
- Use all the wrappers (gzip, zlib, none); not just the default (zlib)
- Pass random sized input and output buffers
- Disable the deflateBound() check for now
This makes the fuzzer cover the bug below.
Bug: 325990053, 40263542
Change-Id: I8ed571b7e84155d2fc0f4f929a5b24a4c9583958
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5310394
Commit-Queue: Hans Wennborg <hans@chromium.org>
Reviewed-by: Adenilson Cavalcanti <cavalcantii@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1263816}
NOKEYCHECK=True
GitOrigin-RevId: 69575154e8a598d1f9347877caf34d71f08e081a
-rw-r--r-- | contrib/tests/fuzzers/deflate_fuzzer.cc | 73 |
1 files changed, 53 insertions, 20 deletions
diff --git a/contrib/tests/fuzzers/deflate_fuzzer.cc b/contrib/tests/fuzzers/deflate_fuzzer.cc index 64892bc..6f3e45e 100644 --- a/contrib/tests/fuzzers/deflate_fuzzer.cc +++ b/contrib/tests/fuzzers/deflate_fuzzer.cc @@ -23,42 +23,75 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { FuzzedDataProvider fdp(data, size); - int level = fdp.PickValueInArray({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + int level = fdp.PickValueInArray({-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); int windowBits = fdp.PickValueInArray({9, 10, 11, 12, 13, 14, 15}); int memLevel = fdp.PickValueInArray({1, 2, 3, 4, 5, 6, 7, 8, 9}); int strategy = fdp.PickValueInArray( {Z_DEFAULT_STRATEGY, Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED}); - std::vector<uint8_t> src = fdp.ConsumeRemainingBytes<uint8_t>(); + + if (fdp.ConsumeBool()) { + // Gzip wrapper. + windowBits += 16; + } else if (fdp.ConsumeBool()) { + // Raw deflate. + windowBits *= -1; + } else { + // Default: zlib wrapper. + } + + std::vector<uint8_t> src; + std::vector<uint8_t> compressed; + static const int kMinChunk = 1; + static const int kMaxChunk = 512 * 1024; z_stream stream; stream.zalloc = Z_NULL; stream.zfree = Z_NULL; - - // Compress the data one byte at a time to exercise the streaming code. int ret = deflateInit2(&stream, level, Z_DEFLATED, windowBits, memLevel, strategy); ASSERT(ret == Z_OK); - size_t deflate_bound = deflateBound(&stream, src.size()); - - std::vector<uint8_t> compressed(src.size() * 2 + 1000); - stream.next_out = compressed.data(); - stream.avail_out = compressed.size(); - for (uint8_t b : src) { - stream.next_in = &b; - stream.avail_in = 1; + // Stream with random-sized input and output buffers. + while (fdp.ConsumeBool()) { + std::vector<uint8_t> src_chunk = fdp.ConsumeBytes<uint8_t>( + fdp.ConsumeIntegralInRange(kMinChunk, kMaxChunk)); + std::vector<uint8_t> out_chunk( + fdp.ConsumeIntegralInRange(kMinChunk, kMaxChunk)); + stream.next_in = src_chunk.data(); + stream.avail_in = src_chunk.size(); + stream.next_out = out_chunk.data(); + stream.avail_out = out_chunk.size(); ret = deflate(&stream, Z_NO_FLUSH); - ASSERT(ret == Z_OK); + ASSERT(ret == Z_OK || ret == Z_BUF_ERROR); + + src.insert(src.end(), src_chunk.begin(), src_chunk.end() - stream.avail_in); + compressed.insert(compressed.end(), out_chunk.begin(), + out_chunk.end() - stream.avail_out); + } + // Finish up. + while (true) { + std::vector<uint8_t> out_chunk( + fdp.ConsumeIntegralInRange(kMinChunk, kMaxChunk)); + stream.next_in = Z_NULL; + stream.avail_in = 0; + stream.next_out = out_chunk.data(); + stream.avail_out = out_chunk.size(); + ret = deflate(&stream, Z_FINISH); + compressed.insert(compressed.end(), out_chunk.begin(), + out_chunk.end() - stream.avail_out); + if (ret == Z_STREAM_END) { + break; + } + ASSERT(ret == Z_OK || Z_BUF_ERROR); } - stream.next_in = Z_NULL; - stream.avail_in = 0; - ret = deflate(&stream, Z_FINISH); - ASSERT(ret == Z_STREAM_END); - compressed.resize(compressed.size() - stream.avail_out); - deflateEnd(&stream); // Check that the bound was correct. - ASSERT(compressed.size() <= deflate_bound); + // size_t deflate_bound = deflateBound(&stream, src.size()); + // TODO(crbug.com/40270738): This does not always hold. + // ASSERT(compressed.size() <= deflate_bound); + + deflateEnd(&stream); + // Verify that the data decompresses correctly. ret = inflateInit2(&stream, windowBits); |