• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <fuzzer/FuzzedDataProvider.h>
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <vector>
12 
13 #include "third_party/zlib/zlib.h"
14 
15 // Fuzzer builds often have NDEBUG set, so roll our own assert macro.
16 #define ASSERT(cond)                                                           \
17   do {                                                                         \
18     if (!(cond)) {                                                             \
19       fprintf(stderr, "%s:%d Assert failed: %s\n", __FILE__, __LINE__, #cond); \
20       exit(1);                                                                 \
21     }                                                                          \
22   } while (0)
23 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)24 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
25   FuzzedDataProvider fdp(data, size);
26   int level = fdp.PickValueInArray({0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
27   int windowBits = fdp.PickValueInArray({9, 10, 11, 12, 13, 14, 15});
28   int memLevel = fdp.PickValueInArray({1, 2, 3, 4, 5, 6, 7, 8, 9});
29   int strategy = fdp.PickValueInArray(
30       {Z_DEFAULT_STRATEGY, Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED});
31   std::vector<uint8_t> src = fdp.ConsumeRemainingBytes<uint8_t>();
32 
33   z_stream stream;
34   stream.zalloc = Z_NULL;
35   stream.zfree = Z_NULL;
36 
37   // Compress the data one byte at a time to exercise the streaming code.
38   int ret =
39       deflateInit2(&stream, level, Z_DEFLATED, windowBits, memLevel, strategy);
40   ASSERT(ret == Z_OK);
41   std::vector<uint8_t> compressed(src.size() * 2 + 1000);
42   stream.next_out = compressed.data();
43   stream.avail_out = compressed.size();
44   for (uint8_t b : src) {
45     stream.next_in = &b;
46     stream.avail_in = 1;
47     ret = deflate(&stream, Z_NO_FLUSH);
48     ASSERT(ret == Z_OK);
49   }
50   stream.next_in = Z_NULL;
51   stream.avail_in = 0;
52   ret = deflate(&stream, Z_FINISH);
53   ASSERT(ret == Z_STREAM_END);
54   compressed.resize(compressed.size() - stream.avail_out);
55   deflateEnd(&stream);
56 
57   // Verify that the data decompresses correctly.
58   ret = inflateInit2(&stream, windowBits);
59   ASSERT(ret == Z_OK);
60   // Make room for at least one byte so it's never empty.
61   std::vector<uint8_t> decompressed(src.size() + 1);
62   stream.next_in = compressed.data();
63   stream.avail_in = compressed.size();
64   stream.next_out = decompressed.data();
65   stream.avail_out = decompressed.size();
66   ret = inflate(&stream, Z_FINISH);
67   ASSERT(ret == Z_STREAM_END);
68   decompressed.resize(decompressed.size() - stream.avail_out);
69   inflateEnd(&stream);
70 
71   ASSERT(decompressed == src);
72 
73   return 0;
74 }
75