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