Coverage Report

Created: 2026-11-12 06:21

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