/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 | | |