Coverage Report

Created: 2026-09-28 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gzio_fuzzer.c
Line
Count
Source
1
/********************************************************************************
2
 * Copyright 2025 Google LLC
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 *
16
 *******************************************************************************/
17
#include <stdio.h>
18
#include <stddef.h>
19
#include <stdint.h>
20
#include <string.h>
21
#include <assert.h>
22
#include <stdlib.h>
23
#include <inttypes.h>
24
#include "zlib.h"
25
26
#undef gzgetc
27
28
2.08k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) {
29
30
2.08k
    gzFile file;
31
2.08k
    char fname[] = "gzio.XXXXXX";
32
2.08k
    close(mkstemp(fname));
33
2.08k
    unsigned mode_sz = (dataLen ? (--dataLen, *data++) | 2 : 8) & 0xF;
34
2.08k
    char mode[mode_sz];
35
2.08k
    memcpy(mode, data, dataLen >= mode_sz ? mode_sz - 1: dataLen);
36
2.08k
    mode[mode_sz - 1] = 0;
37
2.08k
    file = gzopen(fname, mode);
38
39
    /* Chain I/O operations on a file opened with random mode the nature of the
40
     * operation and their operand are controlled by the fuzzer
41
     */
42
2.08k
    int op_count = 2; //< Number of operations chained.
43
5.86k
    while(op_count-- && dataLen > 0) {
44
3.88k
      switch((--dataLen, (*data++)%26)) {
45
103
        case 0: {
46
103
          char c = dataLen ? (--dataLen, (char)*data++) : 'c';
47
103
          if(gzputc(file, c) < 0) {
48
19
            goto exit;
49
19
          }
50
84
          break;
51
103
        }
52
160
        case 1: {
53
160
          unsigned sz = dataLen ? ((--dataLen, *data++)&0xF) + 1 : 8;
54
160
          char input[sz];
55
160
          memcpy(input, data, dataLen >= sz ? sz - 1: dataLen);
56
160
          input[sz - 1] = 0;
57
160
          if(gzputs(file, input) < 0)
58
9
            goto exit;
59
151
          break;
60
160
        }
61
1.08k
        case 2: {
62
1.08k
          unsigned sz = dataLen ? ((--dataLen, *data++)&0xF) + 1 : 8;
63
1.08k
          unsigned nitems = dataLen ? ((--dataLen, *data++)&0xF) + 1 : 8;
64
1.08k
          unsigned count = sz * nitems;
65
1.08k
          char input[count];
66
1.08k
          memcpy(input, data, dataLen >= count ? count - 1: dataLen);
67
1.08k
          input[count - 1] = 0;
68
1.08k
          if(gzfwrite(input, sz, nitems, file) <= 0)
69
17
            goto exit;
70
1.06k
          break;
71
1.08k
        }
72
1.06k
        case 3: {
73
47
          unsigned sz = dataLen ? (--dataLen, *data++) : 8;
74
47
          char uncompr[sz];
75
47
          if(gzread(file, uncompr, sz) < 0)
76
7
            goto exit;
77
40
          break;
78
47
        }
79
361
        case 4: {
80
361
          int whences[5] = {SEEK_CUR, SEEK_SET, SEEK_END, 18};
81
361
          int whence = dataLen ? (--dataLen, whences[(*data++)%5]) : SEEK_CUR;
82
361
          long offset = dataLen >= sizeof(long) ? (*(long*)data &0xFF) + 1: 1L;
83
361
          if(gzseek(file, offset, whence) < 0)
84
19
            goto exit;
85
342
          break;
86
361
        }
87
342
        case 5:
88
24
          gztell(file);
89
24
          break;
90
38
        case 6:
91
38
          gzgetc(file);
92
38
          break;
93
93
        case 7: {
94
93
          char c = dataLen ? (--dataLen, (char)*data++) : 'c';
95
93
          if(gzungetc(c, file) < 0)
96
13
            goto exit;
97
80
          break;
98
93
        }
99
80
        case 8: {
100
76
          unsigned sz = dataLen ? (--dataLen, *data++) : 8;
101
76
          char uncompr[sz];
102
76
          if(gzgets(file, uncompr, sz) < 0)
103
0
            goto exit;
104
76
          break;
105
76
        }
106
214
        case 9: {
107
214
          int level = dataLen ? (--dataLen, *data++) : 1;
108
214
          int strat = dataLen ? (--dataLen, *data++) : 2;
109
214
          if(gzsetparams(file, level, strat) < 0)
110
9
            goto exit;
111
205
          break;
112
214
        }
113
205
        case 10: {
114
201
          int flush = dataLen ? (--dataLen, *data++) : 0;
115
201
          gzflush(file, flush); break;
116
214
        }
117
490
        case 11: {
118
490
          static const char formats [][4] = { "%d", "%f", "%c", "%s" };
119
490
          int nformat = dataLen ? (--dataLen, *data++)%5 : 1;
120
490
          switch(nformat) {
121
54
            case 0: {
122
54
              int value = dataLen >= sizeof(int) ? *(int*)data : 1;
123
54
              gzprintf(file, formats[nformat], value);
124
54
              break;
125
0
            }
126
127
            case 1: {
127
127
              float value = dataLen >= sizeof(float) ? *(float*)data : 1;
128
127
              gzprintf(file, formats[nformat], value);
129
127
              break;
130
0
            }
131
56
            case 2: {
132
56
              char value = dataLen >= sizeof(char) ? *(char*)data : 1;
133
56
              gzprintf(file, formats[nformat], value);
134
56
              break;
135
0
            }
136
101
            case 3: {
137
101
             unsigned sz = dataLen ? ((--dataLen, *data++)&0xF)+1 : 8;
138
101
             char input[sz];
139
101
             memcpy(input, data, dataLen >= sz ? sz - 1: dataLen);
140
101
             input[sz - 1] = 0;
141
101
             gzprintf(file, formats[nformat], input);
142
101
             break;
143
0
            }
144
152
            default: {
145
152
             unsigned sz = dataLen ? ((--dataLen, *data++)&0xF)+1 : 8;
146
152
             char input[sz] = {};
147
152
             memcpy(input, data, dataLen >= sz ? sz - 1: dataLen);
148
1.31k
             for(int i = 0; i < sz - 1; ++i)
149
1.15k
               if(input[i] == '%') input[i] = '!';
150
152
             gzprintf(file, input);
151
152
             break;
152
0
            }
153
490
          };
154
490
          break;
155
490
        }
156
16
        case 12: {
157
16
          gzoffset(file);
158
16
          break;
159
490
        }
160
17
        case 13: {
161
17
          gzrewind(file);
162
17
          break;
163
490
        }
164
17
        case 14: {
165
17
          gzeof(file);
166
17
          break;
167
490
        }
168
172
        case 15: {
169
172
          gzdirect(file);
170
172
          break;
171
490
        }
172
244
        case 16: {
173
244
          unsigned sz = dataLen ? ((--dataLen, *data++))|1 : 128;
174
244
          if(gzbuffer(file, sz) <0)
175
12
            goto exit;
176
232
          break;
177
244
        }
178
232
        case 17: {
179
15
          int errnum;
180
15
          gzerror(file, &errnum);
181
15
          break;
182
244
        }
183
29
        case 18: {
184
29
          gzclearerr(file);
185
29
          break;
186
244
        }
187
271
        case 19: {
188
271
          unsigned sz = dataLen ? (--dataLen, *data++) : 8;
189
271
          unsigned nitems = dataLen ? (--dataLen, *data++) : 8;
190
271
          char buffer[sz * nitems];
191
271
          if(gzfread(buffer, sz, nitems, file) < 0)
192
0
            goto exit;
193
271
          break;
194
271
        }
195
271
        case 20: {
196
24
          gzgetc_(file);
197
24
          break;
198
271
        }
199
46
        case 21: {
200
46
          gzclose(file);
201
46
          file = NULL;
202
46
          break;
203
271
        }
204
20
        case 22: {
205
20
          zlibVersion();
206
20
          break;
207
271
        }
208
33
        case 23: {
209
33
          zlibCompileFlags();
210
33
          break;
211
271
        }
212
29
        case 24: {
213
29
          get_crc_table();
214
29
          break;
215
271
        }
216
60
        case 25: {
217
60
          unsigned err = dataLen ? (--dataLen, *data++) : 0;
218
60
          zError(err);
219
60
          break;
220
271
        }
221
3.88k
      }
222
3.88k
    }
223
1.98k
    gzclose(file);
224
1.98k
    remove(fname);
225
1.98k
  return 0;
226
105
exit:
227
105
    gzclose(file);
228
105
    remove(fname);
229
105
  return -1;
230
2.08k
}