Coverage Report

Created: 2025-06-15 00:57

/src/cmp_tool/test/fuzz/fuzz_compression.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file fuzz_compression.c
3
 * @date 2024
4
 *
5
 * @copyright GPLv2
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms and conditions of the GNU General Public License,
8
 * version 2, as published by the Free Software Foundation.
9
 *
10
 * This program is distributed in the hope it will be useful, but WITHOUT
11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13
 * more details.
14
 *
15
 * @brief chunk compression fuzz target
16
 *
17
 * This fuzzer tests the compression functionality with random data/model and
18
 * parameters. It uses a random portion of the input data for parameter
19
 * generation, while the rest is used for compression.
20
 */
21
22
23
#include <stdint.h>
24
#include <stddef.h>
25
#include <string.h>
26
27
#include "fuzz_helpers.h"
28
#include "fuzz_data_producer.h"
29
30
#include "../../lib/cmp_chunk.h"
31
32
33
34
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
35
1.38k
{
36
1.38k
  struct cmp_par cmp_par;
37
1.38k
  const struct cmp_par *cmp_par_ptr = NULL;
38
1.38k
  const uint8_t *model = NULL;
39
1.38k
  void *up_model;
40
1.38k
  uint32_t *cmp_data;
41
1.38k
  uint32_t cmp_data_capacity;
42
1.38k
  int use_a_upmodel;
43
1.38k
  uint32_t cmp_size_bound;
44
1.38k
  uint32_t return_value;
45
46
  /* Give a random portion of src data to the producer, to use for
47
     parameter generation. The rest will be used for data/model */
48
1.38k
  FUZZ_dataProducer_t *producer = (FUZZ_dataProducer_t *)FUZZ_dataProducer_create(src, size);
49
50
1.38k
  size = FUZZ_dataProducer_reserveDataPrefix(producer);
51
52
1.38k
  FUZZ_dataProducer_cmp_par(producer, &cmp_par);
53
54
  /* 1/2 of the cases we use a model */
55
1.38k
  if (FUZZ_dataProducer_uint32Range(producer, 0, 1) && size > 2) {
56
365
    model = src + size/2;
57
365
    size /= 2;
58
365
  }
59
1.38k
  FUZZ_ASSERT(size <= UINT32_MAX);
60
61
1.38k
  cmp_size_bound = compress_chunk_cmp_size_bound(src, size);
62
1.38k
  if (cmp_is_error(cmp_size_bound))
63
255
    cmp_size_bound = 0;
64
1.38k
  cmp_data_capacity = FUZZ_dataProducer_uint32Range(producer, 0, cmp_size_bound+(uint32_t)size);
65
1.38k
  cmp_data = (uint32_t *)FUZZ_malloc(cmp_data_capacity);
66
67
1.38k
  FUZZ_dataProducer_cmp_par(producer, &cmp_par);
68
1.38k
  if (FUZZ_dataProducer_uint32Range(producer, 0, 1))
69
1.25k
    cmp_par_ptr = &cmp_par;
70
71
1.38k
  use_a_upmodel = FUZZ_dataProducer_int32Range(producer, 0, 2);
72
1.38k
  switch (use_a_upmodel) {
73
823
  case 0:
74
823
    up_model = NULL;
75
823
    break;
76
310
  case 1:
77
310
    up_model = FUZZ_malloc(size);
78
310
    break;
79
247
  case 2:
80
247
    up_model = FUZZ_malloc(size);
81
247
    if (model && up_model) {
82
75
      memcpy(up_model, model, size);
83
75
      model = up_model; /* in-place update */
84
75
    }
85
247
    break;
86
0
  default:
87
0
    FUZZ_ASSERT(0);
88
1.38k
  }
89
90
91
1.38k
  return_value = compress_chunk(src, (uint32_t)size, model, up_model,
92
1.38k
              cmp_data, cmp_data_capacity, cmp_par_ptr);
93
94
1.38k
  switch (cmp_get_error_code(return_value)) {
95
701
  case CMP_ERROR_NO_ERROR:
96
701
  case CMP_ERROR_GENERIC:
97
816
  case CMP_ERROR_SMALL_BUFFER:
98
  /* compression parameter errors */
99
820
  case CMP_ERROR_PAR_GENERIC:
100
858
  case CMP_ERROR_PAR_SPECIFIC:
101
858
  case CMP_ERROR_PAR_BUFFERS:
102
987
  case CMP_ERROR_PAR_NULL:
103
991
  case CMP_ERROR_PAR_NO_MODEL:
104
  /* chunk errors */
105
991
  case CMP_ERROR_CHUNK_NULL:
106
991
  case CMP_ERROR_CHUNK_TOO_LARGE:
107
991
  case CMP_ERROR_CHUNK_TOO_SMALL:
108
1.05k
  case CMP_ERROR_CHUNK_SIZE_INCONSISTENT:
109
1.13k
  case CMP_ERROR_CHUNK_SUBSERVICE_INCONSISTENT:
110
  /* collection errors */
111
1.13k
  case CMP_ERROR_COL_SUBSERVICE_UNSUPPORTED:
112
1.13k
  case CMP_ERROR_COL_SIZE_INCONSISTENT:
113
1.13k
    break;
114
  /* compression entity errors */
115
0
  case CMP_ERROR_ENTITY_NULL:
116
0
    FUZZ_ASSERT(0);
117
0
  case CMP_ERROR_ENTITY_TOO_SMALL:
118
0
    FUZZ_ASSERT(0);
119
241
  case CMP_ERROR_ENTITY_HEADER:
120
241
    break;
121
0
  case CMP_ERROR_ENTITY_TIMESTAMP:
122
0
    FUZZ_ASSERT(0);
123
  /* internal compressor errors */
124
0
  case CMP_ERROR_INT_DECODER:
125
0
    FUZZ_ASSERT(0);
126
0
  case CMP_ERROR_INT_DATA_TYPE_UNSUPPORTED:
127
0
    FUZZ_ASSERT(0);
128
0
  case CMP_ERROR_INT_CMP_COL_TOO_LARGE:
129
0
    FUZZ_ASSERT(0);
130
131
0
  case CMP_ERROR_DATA_VALUE_TOO_LARGE:
132
0
    FUZZ_ASSERT(0);
133
0
  default:
134
0
    FUZZ_ASSERT(0);
135
1.38k
  }
136
1.38k
  if (!cmp_is_error(return_value) && model != up_model) {
137
469
    uint32_t return_value2;
138
139
469
    return_value2 = compress_chunk(src, (uint32_t)size, model, up_model,
140
469
                 NULL, cmp_data_capacity, cmp_par_ptr);
141
469
    FUZZ_ASSERT(return_value == return_value2);
142
469
  }
143
144
0
  free(cmp_data);
145
1.38k
  free(up_model);
146
1.38k
  FUZZ_dataProducer_free(producer);
147
1.38k
  return 0;
148
1.38k
}
149