• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <assert.h>
3 #include <inttypes.h>
4 
5 #include "zbuild.h"
6 #ifdef ZLIB_COMPAT
7 #  include "zlib.h"
8 #else
9 #  include "zlib-ng.h"
10 #endif
11 
12 #define CHECK_ERR(err, msg) { \
13     if (err != Z_OK) { \
14         fprintf(stderr, "%s error: %d\n", msg, err); \
15         exit(1); \
16     } \
17 }
18 
19 static const uint8_t *data;
20 static size_t dataLen;
21 static alloc_func zalloc = NULL;
22 static free_func zfree = NULL;
23 static unsigned int diff;
24 
25 /* ===========================================================================
26  * Test deflate() with large buffers and dynamic change of compression level
27  */
test_large_deflate(unsigned char * compr,size_t comprLen,unsigned char * uncompr,size_t uncomprLen)28 void test_large_deflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) {
29     PREFIX3(stream) c_stream; /* compression stream */
30     int err;
31 
32     c_stream.zalloc = zalloc;
33     c_stream.zfree = zfree;
34     c_stream.opaque = (void *)0;
35 
36     err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION);
37     CHECK_ERR(err, "deflateInit");
38 
39     c_stream.next_out = compr;
40     c_stream.avail_out = (unsigned int)comprLen;
41 
42     /* At this point, uncompr is still mostly zeroes, so it should compress
43      * very well:
44      */
45     c_stream.next_in = uncompr;
46     c_stream.avail_in = (unsigned int)uncomprLen;
47     err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
48     CHECK_ERR(err, "deflate large 1");
49     if (c_stream.avail_in != 0) {
50         fprintf(stderr, "deflate not greedy\n");
51         exit(1);
52     }
53 
54     /* Feed in already compressed data and switch to no compression: */
55     PREFIX(deflateParams)(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
56     c_stream.next_in = compr;
57     diff = (unsigned int)(c_stream.next_out - compr);
58     c_stream.avail_in = diff;
59     err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
60     CHECK_ERR(err, "deflate large 2");
61 
62     /* Switch back to compressing mode: */
63     PREFIX(deflateParams)(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
64     c_stream.next_in = uncompr;
65     c_stream.avail_in = (unsigned int)uncomprLen;
66     err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
67     CHECK_ERR(err, "deflate large 3");
68 
69     err = PREFIX(deflate)(&c_stream, Z_FINISH);
70     if (err != Z_STREAM_END) {
71         fprintf(stderr, "deflate large should report Z_STREAM_END\n");
72         exit(1);
73     }
74     err = PREFIX(deflateEnd)(&c_stream);
75     CHECK_ERR(err, "deflateEnd");
76 }
77 
78 /* ===========================================================================
79  * Test inflate() with large buffers
80  */
test_large_inflate(unsigned char * compr,size_t comprLen,unsigned char * uncompr,size_t uncomprLen)81 void test_large_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) {
82     int err;
83     PREFIX3(stream) d_stream; /* decompression stream */
84 
85     d_stream.zalloc = zalloc;
86     d_stream.zfree = zfree;
87     d_stream.opaque = (void *)0;
88 
89     d_stream.next_in = compr;
90     d_stream.avail_in = (unsigned int)comprLen;
91 
92     err = PREFIX(inflateInit)(&d_stream);
93     CHECK_ERR(err, "inflateInit");
94 
95     for (;;) {
96         d_stream.next_out = uncompr; /* discard the output */
97         d_stream.avail_out = (unsigned int)uncomprLen;
98         err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
99         if (err == Z_STREAM_END)
100             break;
101         CHECK_ERR(err, "large inflate");
102     }
103 
104     err = PREFIX(inflateEnd)(&d_stream);
105     CHECK_ERR(err, "inflateEnd");
106 
107     if (d_stream.total_out != 2 * uncomprLen + diff) {
108         fprintf(stderr, "bad large inflate: %" PRIu64 "\n", (uint64_t)d_stream.total_out);
109         exit(1);
110     }
111 }
112 
LLVMFuzzerTestOneInput(const uint8_t * d,size_t size)113 int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
114     size_t comprLen = 100 + 3 * size;
115     size_t uncomprLen = comprLen;
116     uint8_t *compr, *uncompr;
117 
118     /* Discard inputs larger than 512Kb. */
119     static size_t kMaxSize = 512 * 1024;
120 
121     if (size < 1 || size > kMaxSize)
122         return 0;
123 
124     data = d;
125     dataLen = size;
126     compr = (uint8_t *)calloc(1, comprLen);
127     uncompr = (uint8_t *)calloc(1, uncomprLen);
128 
129     test_large_deflate(compr, comprLen, uncompr, uncomprLen);
130     test_large_inflate(compr, comprLen, uncompr, uncomprLen);
131 
132     free(compr);
133     free(uncompr);
134 
135     /* This function must return 0. */
136     return 0;
137 }
138