1 // Copyright 2020 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 <stddef.h>
6 #include <stdint.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 
10 #include "third_party/zlib/zlib.h"
11 
12 // Fuzzer builds often have NDEBUG set, so roll our own assert macro.
13 #define ASSERT(cond)                                                           \
14   do {                                                                         \
15     if (!(cond)) {                                                             \
16       fprintf(stderr, "%s:%d Assert failed: %s\n", __FILE__, __LINE__, #cond); \
17       exit(1);                                                                 \
18     }                                                                          \
19   } while (0)
20 
21 // Entry point for LibFuzzer.
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)22 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
23   // Deflate data.
24   z_stream comp_strm;
25   comp_strm.zalloc = Z_NULL;
26   comp_strm.zfree = Z_NULL;
27   comp_strm.opaque = Z_NULL;
28   int ret = deflateInit(&comp_strm, Z_DEFAULT_COMPRESSION);
29   ASSERT(ret == Z_OK);
30 
31   size_t comp_buf_cap = deflateBound(&comp_strm, size);
32   uint8_t* comp_buf = (uint8_t*)malloc(comp_buf_cap);
33   ASSERT(comp_buf != nullptr);
34   comp_strm.next_out = comp_buf;
35   comp_strm.avail_out = comp_buf_cap;
36   comp_strm.next_in = (unsigned char*)data;
37   comp_strm.avail_in = size;
38   ret = deflate(&comp_strm, Z_FINISH);
39   ASSERT(ret == Z_STREAM_END);
40   size_t comp_sz = comp_buf_cap - comp_strm.avail_out;
41 
42   // Inflate comp_buf one chunk at a time.
43   z_stream decomp_strm;
44   decomp_strm.zalloc = Z_NULL;
45   decomp_strm.zfree = Z_NULL;
46   decomp_strm.opaque = Z_NULL;
47   ret = inflateInit(&decomp_strm);
48   ASSERT(ret == Z_OK);
49   decomp_strm.next_in = comp_buf;
50   decomp_strm.avail_in = comp_sz;
51 
52   while (decomp_strm.avail_in > 0) {
53     uint8_t decomp_buf[1024];
54     decomp_strm.next_out = decomp_buf;
55     decomp_strm.avail_out = sizeof(decomp_buf);
56     ret = inflate(&decomp_strm, Z_FINISH);
57     ASSERT(ret == Z_OK || ret == Z_STREAM_END || ret == Z_BUF_ERROR);
58 
59     // Verify the output bytes.
60     size_t num_out = sizeof(decomp_buf) - decomp_strm.avail_out;
61     for (size_t i = 0; i < num_out; i++) {
62       ASSERT(decomp_buf[i] == data[decomp_strm.total_out - num_out + i]);
63     }
64   }
65 
66   ret = deflateEnd(&comp_strm);
67   ASSERT(ret == Z_OK);
68   free(comp_buf);
69 
70   inflateEnd(&decomp_strm);
71   ASSERT(ret == Z_OK);
72 
73   return 0;
74 }
75