Coverage Report

Created: 2023-09-25 07:00

/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
20.7k
#define CHECK_ERR(err, msg) { \
23
20.7k
    if (err != Z_OK) { \
24
0
        fprintf(stderr, "%s error: %d\n", msg, err); \
25
0
        return 0; \
26
0
    } \
27
20.7k
}
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
2.95k
int test_flush(unsigned char *compr, z_size_t *comprLen) {
38
2.95k
  z_stream c_stream; /* compression stream */
39
2.95k
  int err;
40
2.95k
  unsigned int len = dataLen;
41
42
2.95k
  c_stream.zalloc = zalloc;
43
2.95k
  c_stream.zfree = zfree;
44
2.95k
  c_stream.opaque = (void *)0;
45
46
2.95k
  err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
47
2.95k
  CHECK_ERR(err, "deflateInit");
48
49
2.95k
  c_stream.next_in = (Bytef *)data;
50
2.95k
  c_stream.next_out = compr;
51
2.95k
  c_stream.avail_in = 3;
52
2.95k
  c_stream.avail_out = (unsigned int)*comprLen;
53
2.95k
  err = deflate(&c_stream, Z_FULL_FLUSH);
54
2.95k
  CHECK_ERR(err, "deflate flush 1");
55
56
2.95k
  compr[3]++; /* force an error in first compressed block */
57
2.95k
  c_stream.avail_in = len - 3;
58
59
2.95k
  err = deflate(&c_stream, Z_FINISH);
60
2.95k
  if (err != Z_STREAM_END) {
61
0
    CHECK_ERR(err, "deflate flush 2");
62
0
  }
63
2.95k
  err = deflateEnd(&c_stream);
64
2.95k
  CHECK_ERR(err, "deflateEnd");
65
66
2.95k
  *comprLen = (z_size_t)c_stream.total_out;
67
68
2.95k
  return 0;
69
2.95k
}
70
71
/* ===========================================================================
72
 * Test inflateSync()
73
 */
74
int test_sync(unsigned char *compr, size_t comprLen, unsigned char *uncompr,
75
2.95k
               size_t uncomprLen) {
76
2.95k
  int err;
77
2.95k
  z_stream d_stream; /* decompression stream */
78
79
2.95k
  d_stream.zalloc = zalloc;
80
2.95k
  d_stream.zfree = zfree;
81
2.95k
  d_stream.opaque = (void *)0;
82
83
2.95k
  d_stream.next_in = compr;
84
2.95k
  d_stream.avail_in = 2; /* just read the zlib header */
85
86
2.95k
  err = inflateInit(&d_stream);
87
2.95k
  CHECK_ERR(err, "inflateInit");
88
89
2.95k
  d_stream.next_out = uncompr;
90
2.95k
  d_stream.avail_out = (unsigned int)uncomprLen;
91
92
2.95k
  err = inflate(&d_stream, Z_NO_FLUSH);
93
2.95k
  CHECK_ERR(err, "inflate");
94
95
2.95k
  d_stream.avail_in = (unsigned int)comprLen - 2; /* read all compressed data */
96
2.95k
  err = inflateSync(&d_stream); /* but skip the damaged part */
97
2.95k
  CHECK_ERR(err, "inflateSync");
98
99
2.95k
  err = inflate(&d_stream, Z_FINISH);
100
2.95k
  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
2.95k
  err = inflateEnd(&d_stream);
106
2.95k
  CHECK_ERR(err, "inflateEnd");
107
2.95k
  return 0;
108
2.95k
}
109
110
2.96k
int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
111
2.96k
  size_t comprLen = 100 + 2 * compressBound(size);
112
2.96k
  size_t uncomprLen = size;
113
2.96k
  uint8_t *compr, *uncompr;
114
115
  /* Discard inputs larger than 1Mb. */
116
2.96k
  static size_t kMaxSize = 1024 * 1024;
117
118
  // This test requires at least 3 bytes of input data.
119
2.96k
  if (size <= 3 || size > kMaxSize)
120
2
    return 0;
121
122
2.95k
  data = d;
123
2.95k
  dataLen = size;
124
2.95k
  compr = (uint8_t *)calloc(1, comprLen);
125
2.95k
  uncompr = (uint8_t *)calloc(1, uncomprLen);
126
127
2.95k
  test_flush(compr, &comprLen);
128
2.95k
  test_sync(compr, comprLen, uncompr, uncomprLen);
129
130
2.95k
  free(compr);
131
2.95k
  free(uncompr);
132
133
  /* This function must return 0. */
134
2.95k
  return 0;
135
2.96k
}