Coverage Report

Created: 2025-12-14 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/zlib-ng/test/fuzz/fuzzer_example_dict.c
Line
Count
Source
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
59.6k
#define CHECK_ERR(err, msg) { \
12
59.6k
    if (err != Z_OK) { \
13
0
        fprintf(stderr, "%s error: %d\n", msg, err); \
14
0
        exit(1); \
15
0
    } \
16
59.6k
}
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
static unsigned int dictionaryLen = 0;
23
static unsigned long dictId; /* Adler32 value of the dictionary */
24
25
/* ===========================================================================
26
 * Test deflate() with preset dictionary
27
 */
28
9.99k
void test_dict_deflate(unsigned char **compr, size_t *comprLen) {
29
9.99k
    PREFIX3(stream) c_stream; /* compression stream */
30
9.99k
    int err;
31
9.99k
    int level = data[0] % 11 - 1; /* [-1..9]
32
      compression levels
33
      #define Z_NO_COMPRESSION         0
34
      #define Z_BEST_SPEED             1
35
      #define Z_BEST_COMPRESSION       9
36
      #define Z_DEFAULT_COMPRESSION  (-1) */
37
38
9.99k
    int method = Z_DEFLATED; /* The deflate compression method (the only one
39
                                supported in this version) */
40
9.99k
    int windowBits = 8 + data[(dataLen > 1) ? 1:0] % 8; /* The windowBits parameter is the base
41
      two logarithm of the window size (the size of the history buffer).  It
42
      should be in the range 8..15 for this version of the library. */
43
9.99k
    int memLevel = 1 + data[(dataLen > 2) ? 2:0] % 9;   /* memLevel=1 uses minimum memory but is
44
      slow and reduces compression ratio; memLevel=9 uses maximum memory for
45
      optimal speed. */
46
9.99k
    int strategy = data[(dataLen > 3) ? 3:0] % 5;       /* [0..4]
47
      #define Z_FILTERED            1
48
      #define Z_HUFFMAN_ONLY        2
49
      #define Z_RLE                 3
50
      #define Z_FIXED               4
51
      #define Z_DEFAULT_STRATEGY    0 */
52
53
    /* deflate would fail for no-compression or for speed levels. */
54
9.99k
    if (level == 0 || level == 1)
55
3.11k
        level = -1;
56
57
9.99k
    c_stream.zalloc = zalloc;
58
9.99k
    c_stream.zfree = zfree;
59
9.99k
    c_stream.opaque = (void *)0;
60
61
9.99k
    err = PREFIX(deflateInit2)(&c_stream, level, method, windowBits, memLevel,
62
9.99k
                               strategy);
63
9.99k
    CHECK_ERR(err, "deflateInit");
64
65
9.99k
    err = PREFIX(deflateSetDictionary)(
66
9.99k
        &c_stream, (const unsigned char *)data, dictionaryLen);
67
9.99k
    CHECK_ERR(err, "deflateSetDictionary");
68
69
    /* deflateBound does not provide enough space for low compression levels. */
70
9.99k
    *comprLen = 100 + 2 * PREFIX(deflateBound)(&c_stream, (unsigned long)dataLen);
71
9.99k
    *compr = (uint8_t *)calloc(1, *comprLen);
72
73
9.99k
    dictId = c_stream.adler;
74
9.99k
    c_stream.next_out = *compr;
75
9.99k
    c_stream.avail_out = (unsigned int)(*comprLen);
76
77
9.99k
    c_stream.next_in = (z_const unsigned char *)data;
78
9.99k
    c_stream.avail_in = (uint32_t)dataLen;
79
80
9.99k
    err = PREFIX(deflate)(&c_stream, Z_FINISH);
81
9.99k
    if (err != Z_STREAM_END) {
82
0
        fprintf(stderr, "deflate dict should report Z_STREAM_END\n");
83
0
        exit(1);
84
0
    }
85
9.99k
    err = PREFIX(deflateEnd)(&c_stream);
86
9.99k
    CHECK_ERR(err, "deflateEnd");
87
9.99k
}
88
89
/* ===========================================================================
90
 * Test inflate() with a preset dictionary
91
 */
92
9.99k
void test_dict_inflate(unsigned char *compr, size_t comprLen) {
93
9.99k
    int err;
94
9.99k
    PREFIX3(stream) d_stream; /* decompression stream */
95
9.99k
    unsigned char *uncompr;
96
97
9.99k
    d_stream.zalloc = zalloc;
98
9.99k
    d_stream.zfree = zfree;
99
9.99k
    d_stream.opaque = (void *)0;
100
101
9.99k
    d_stream.next_in = compr;
102
9.99k
    d_stream.avail_in = (unsigned int)comprLen;
103
104
9.99k
    err = PREFIX(inflateInit)(&d_stream);
105
9.99k
    CHECK_ERR(err, "inflateInit");
106
107
9.99k
    uncompr = (uint8_t *)calloc(1, dataLen);
108
9.99k
    d_stream.next_out = uncompr;
109
9.99k
    d_stream.avail_out = (unsigned int)dataLen;
110
111
19.6k
    for (;;) {
112
19.6k
        err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
113
19.6k
        if (err == Z_STREAM_END)
114
9.99k
            break;
115
9.70k
        if (err == Z_NEED_DICT) {
116
9.70k
            if (d_stream.adler != dictId) {
117
0
                fprintf(stderr, "unexpected dictionary");
118
0
                exit(1);
119
0
            }
120
9.70k
            err = PREFIX(inflateSetDictionary)(
121
9.70k
                    &d_stream, (const unsigned char *)data, dictionaryLen);
122
9.70k
        }
123
9.70k
        CHECK_ERR(err, "inflate with dict");
124
9.70k
    }
125
126
9.99k
    err = PREFIX(inflateEnd)(&d_stream);
127
9.99k
    CHECK_ERR(err, "inflateEnd");
128
129
9.99k
    if (memcmp(uncompr, data, dataLen)) {
130
0
        fprintf(stderr, "bad inflate with dict\n");
131
0
        exit(1);
132
0
    }
133
134
9.99k
    free(uncompr);
135
9.99k
}
136
137
10.0k
int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
138
10.0k
    size_t comprLen = 0;
139
10.0k
    uint8_t *compr;
140
141
    /* Discard inputs larger than 100Kb. */
142
10.0k
    static size_t kMaxSize = 100 * 1024;
143
144
10.0k
    if (size < 1 || size > kMaxSize)
145
8
        return 0;
146
147
9.99k
    data = d;
148
9.99k
    dataLen = size;
149
150
    /* Set up the contents of the dictionary. The size of the dictionary is
151
       intentionally selected to be of unusual size. To help cover more corner
152
       cases, the size of the dictionary is read from the input data. */
153
9.99k
    dictionaryLen = data[0];
154
9.99k
    if (dictionaryLen > dataLen)
155
3.87k
        dictionaryLen = (unsigned int)dataLen;
156
157
9.99k
    test_dict_deflate(&compr, &comprLen);
158
9.99k
    test_dict_inflate(compr, comprLen);
159
160
9.99k
    free(compr);
161
162
    /* This function must return 0. */
163
9.99k
    return 0;
164
10.0k
}