Coverage Report

Created: 2025-07-01 07:02

/src/example_flush_fuzzer.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright 2022 Google LLC
2
Licensed under the Apache License, Version 2.0 (the "License");
3
you may not use this file except in compliance with the License.
4
You may obtain a copy of the License at
5
      http://www.apache.org/licenses/LICENSE-2.0
6
Unless required by applicable law or agreed to in writing, software
7
distributed under the License is distributed on an "AS IS" BASIS,
8
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
See the License for the specific language governing permissions and
10
limitations under the License.
11
*/
12
13
#include <stdio.h>
14
#include <stddef.h>
15
#include <stdint.h>
16
#include <string.h>
17
#include <assert.h>
18
#include <stdlib.h>
19
#include <inttypes.h>
20
#include "zlib.h"
21
22
0
#define CHECK_ERR(err, msg) { \
23
0
    if (err != Z_OK) { \
24
0
        fprintf(stderr, "%s error: %d\n", msg, err); \
25
0
        return 0; \
26
0
    } \
27
0
}
28
29
static const uint8_t *data;
30
static size_t dataLen;
31
static alloc_func zalloc = NULL;
32
static free_func zfree = NULL;
33
34
/* ===========================================================================
35
 * Test deflate() with full flush
36
 */
37
0
int test_flush(unsigned char *compr, z_size_t *comprLen) {
38
0
  z_stream c_stream; /* compression stream */
39
0
  int err;
40
0
  unsigned int len = dataLen;
41
42
0
  c_stream.zalloc = zalloc;
43
0
  c_stream.zfree = zfree;
44
0
  c_stream.opaque = (void *)0;
45
46
0
  err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
47
0
  CHECK_ERR(err, "deflateInit");
48
49
0
  c_stream.next_in = (Bytef *)data;
50
0
  c_stream.next_out = compr;
51
0
  c_stream.avail_in = 3;
52
0
  c_stream.avail_out = (unsigned int)*comprLen;
53
0
  err = deflate(&c_stream, Z_FULL_FLUSH);
54
0
  CHECK_ERR(err, "deflate flush 1");
55
56
0
  compr[3]++; /* force an error in first compressed block */
57
0
  c_stream.avail_in = len - 3;
58
59
0
  err = deflate(&c_stream, Z_FINISH);
60
0
  if (err != Z_STREAM_END) {
61
0
    CHECK_ERR(err, "deflate flush 2");
62
0
  }
63
0
  err = deflateEnd(&c_stream);
64
0
  CHECK_ERR(err, "deflateEnd");
65
66
0
  *comprLen = (z_size_t)c_stream.total_out;
67
68
0
  return 0;
69
0
}
70
71
/* ===========================================================================
72
 * Test inflateSync()
73
 */
74
int test_sync(unsigned char *compr, size_t comprLen, unsigned char *uncompr,
75
0
               size_t uncomprLen) {
76
0
  int err;
77
0
  z_stream d_stream; /* decompression stream */
78
79
0
  d_stream.zalloc = zalloc;
80
0
  d_stream.zfree = zfree;
81
0
  d_stream.opaque = (void *)0;
82
83
0
  d_stream.next_in = compr;
84
0
  d_stream.avail_in = 2; /* just read the zlib header */
85
86
0
  err = inflateInit(&d_stream);
87
0
  CHECK_ERR(err, "inflateInit");
88
89
0
  d_stream.next_out = uncompr;
90
0
  d_stream.avail_out = (unsigned int)uncomprLen;
91
92
0
  err = inflate(&d_stream, Z_NO_FLUSH);
93
0
  CHECK_ERR(err, "inflate");
94
95
0
  d_stream.avail_in = (unsigned int)comprLen - 2; /* read all compressed data */
96
0
  err = inflateSync(&d_stream); /* but skip the damaged part */
97
0
  CHECK_ERR(err, "inflateSync");
98
99
0
  err = inflate(&d_stream, Z_FINISH);
100
0
  if (err != Z_DATA_ERROR && err != Z_STREAM_END) {
101
0
    fprintf(stderr, "inflate should report DATA_ERROR or Z_STREAM_END\n");
102
    /* v1.1.11= reports DATA_ERROR because of incorrect adler32. v1.1.12+ reports Z_STREAM END because it skips the adler32 check. */
103
0
    return 0;
104
0
  }
105
0
  err = inflateEnd(&d_stream);
106
0
  CHECK_ERR(err, "inflateEnd");
107
0
  return 0;
108
0
}
109
110
int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
111
  size_t comprLen = 100 + 2 * compressBound(size);
112
  size_t uncomprLen = size;
113
  uint8_t *compr, *uncompr;
114
115
  /* Discard inputs larger than 1Mb. */
116
  static size_t kMaxSize = 1024 * 1024;
117
118
  // This test requires at least 3 bytes of input data.
119
  if (size <= 3 || size > kMaxSize)
120
    return 0;
121
122
  data = d;
123
  dataLen = size;
124
  compr = (uint8_t *)calloc(1, comprLen);
125
  uncompr = (uint8_t *)calloc(1, uncomprLen);
126
127
  test_flush(compr, &comprLen);
128
  test_sync(compr, comprLen, uncompr, uncomprLen);
129
130
  free(compr);
131
  free(uncompr);
132
133
  /* This function must return 0. */
134
  return 0;
135
}