• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <assert.h>
3 
4 #include "zbuild.h"
5 #ifdef ZLIB_COMPAT
6 #  include "zlib.h"
7 #else
8 #  include "zlib-ng.h"
9 #endif
10 
11 #define CHECK_ERR(err, msg) { \
12     if (err != Z_OK) { \
13         fprintf(stderr, "%s error: %d\n", msg, err); \
14         exit(1); \
15     } \
16 }
17 
18 static const uint8_t *data;
19 static size_t dataLen;
20 static alloc_func zalloc = NULL;
21 static free_func zfree = NULL;
22 
23 /* ===========================================================================
24  * Test deflate() with small buffers
25  */
test_deflate(unsigned char * compr,size_t comprLen)26 void test_deflate(unsigned char *compr, size_t comprLen) {
27     PREFIX3(stream) c_stream; /* compression stream */
28     int err;
29     unsigned long len = (unsigned long)dataLen;
30 
31     c_stream.zalloc = zalloc;
32     c_stream.zfree = zfree;
33     c_stream.opaque = (void *)0;
34 
35     err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION);
36     CHECK_ERR(err, "deflateInit");
37 
38     c_stream.next_in = (z_const unsigned char *)data;
39     c_stream.next_out = compr;
40 
41     while (c_stream.total_in != len && c_stream.total_out < comprLen) {
42         c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
43         err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
44         CHECK_ERR(err, "deflate small 1");
45     }
46     /* Finish the stream, still forcing small buffers: */
47     for (;;) {
48         c_stream.avail_out = 1;
49         err = PREFIX(deflate)(&c_stream, Z_FINISH);
50         if (err == Z_STREAM_END)
51             break;
52         CHECK_ERR(err, "deflate small 2");
53     }
54 
55     err = PREFIX(deflateEnd)(&c_stream);
56     CHECK_ERR(err, "deflateEnd");
57 }
58 
59 /* ===========================================================================
60  * Test inflate() with small buffers
61  */
test_inflate(unsigned char * compr,size_t comprLen,unsigned char * uncompr,size_t uncomprLen)62 void test_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) {
63     int err;
64     PREFIX3(stream) d_stream; /* decompression stream */
65 
66     d_stream.zalloc = zalloc;
67     d_stream.zfree = zfree;
68     d_stream.opaque = (void *)0;
69 
70     d_stream.next_in = compr;
71     d_stream.avail_in = 0;
72     d_stream.next_out = uncompr;
73 
74     err = PREFIX(inflateInit)(&d_stream);
75     CHECK_ERR(err, "inflateInit");
76 
77     while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
78         d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
79         err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
80         if (err == Z_STREAM_END)
81             break;
82         CHECK_ERR(err, "inflate");
83     }
84 
85     err = PREFIX(inflateEnd)(&d_stream);
86     CHECK_ERR(err, "inflateEnd");
87 
88     if (memcmp(uncompr, data, dataLen)) {
89         fprintf(stderr, "bad inflate\n");
90         exit(1);
91     }
92 }
93 
LLVMFuzzerTestOneInput(const uint8_t * d,size_t size)94 int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
95     size_t comprLen = PREFIX(compressBound)(size);
96     size_t uncomprLen = size;
97     uint8_t *compr, *uncompr;
98 
99     /* Discard inputs larger than 1Mb. */
100     static size_t kMaxSize = 1024 * 1024;
101 
102     if (size < 1 || size > kMaxSize)
103         return 0;
104 
105     data = d;
106     dataLen = size;
107     compr = (uint8_t *)calloc(1, comprLen);
108     uncompr = (uint8_t *)calloc(1, uncomprLen);
109 
110     test_deflate(compr, comprLen);
111     test_inflate(compr, comprLen, uncompr, uncomprLen);
112 
113     free(compr);
114     free(uncompr);
115 
116     /* This function must return 0. */
117     return 0;
118 }
119