/src/cmp_tool/test/fuzz/fuzz_round_trip.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * @file fuzz_round_trip.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/decompression fuzz target |
16 | | * |
17 | | * This fuzzer tests the (de)compression functionality with random data/model |
18 | | * and parameters. It uses a random portion of the input data for parameter |
19 | | * generation, while the rest is used for compression. If the compression |
20 | | * succeeds, the data are decompressed and checked to see whether they match the |
21 | | * input data. |
22 | | */ |
23 | | |
24 | | #include <string.h> |
25 | | #include <stdlib.h> |
26 | | |
27 | | #include "fuzz_helpers.h" |
28 | | #include "fuzz_data_producer.h" |
29 | | #include "../test_common/chunk_round_trip.h" |
30 | | |
31 | | |
32 | | int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) |
33 | 2.70k | { |
34 | 2.70k | struct cmp_par cmp_par; |
35 | 2.70k | struct cmp_par *cmp_par_ptr = NULL; |
36 | 2.70k | const uint8_t *model = NULL; |
37 | 2.70k | void *up_model = NULL; |
38 | 2.70k | uint32_t cmp_size_bound; |
39 | 2.70k | uint32_t *cmp_data; |
40 | 2.70k | uint32_t cmp_data_capacity; |
41 | 2.70k | uint32_t return_value; |
42 | 2.70k | int use_decmp_buf; |
43 | 2.70k | int use_decmp_up_model; |
44 | | |
45 | | /* Give a random portion of src data to the producer, to use for |
46 | | parameter generation. The rest will be used for (de)compression */ |
47 | 2.70k | FUZZ_dataProducer_t *producer = (FUZZ_dataProducer_t *)FUZZ_dataProducer_create(src, size); |
48 | | |
49 | 2.70k | size = FUZZ_dataProducer_reserveDataPrefix(producer); |
50 | | |
51 | | /* 1/2 of the cases we use a model */ |
52 | 2.70k | if (FUZZ_dataProducer_uint32Range(producer, 0, 1) && size > 2) { |
53 | 1.37k | model = src + size/2; |
54 | 1.37k | size /= 2; |
55 | 1.37k | } |
56 | 2.70k | FUZZ_ASSERT(size <= UINT32_MAX); |
57 | | |
58 | | /* generate compression parameters */ |
59 | 2.70k | FUZZ_dataProducer_cmp_par(producer, &cmp_par); |
60 | 2.70k | if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) |
61 | 2.56k | cmp_par_ptr = &cmp_par; |
62 | | |
63 | | /* 1/2 of the cases we use a updated model buffer */ |
64 | 2.70k | if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) { |
65 | 1.99k | up_model = FUZZ_malloc(size); |
66 | 1.99k | if (!model_mode_is_used(cmp_par.cmp_mode)) |
67 | 753 | memset(up_model, 0, size); /* up_model is not used */ |
68 | 1.99k | } |
69 | | |
70 | 2.70k | cmp_size_bound = compress_chunk_cmp_size_bound(src, size); |
71 | 2.70k | if (cmp_is_error(cmp_size_bound)) |
72 | 543 | cmp_size_bound = 0; |
73 | 2.70k | cmp_data_capacity = FUZZ_dataProducer_uint32Range(producer, 0, cmp_size_bound+(uint32_t)size); |
74 | 2.70k | cmp_data = (uint32_t *)FUZZ_malloc(cmp_data_capacity); |
75 | | |
76 | 2.70k | use_decmp_buf = FUZZ_dataProducer_int32Range(producer, 0, 1); |
77 | 2.70k | use_decmp_up_model = FUZZ_dataProducer_int32Range(producer, 0, 1); |
78 | | |
79 | 2.70k | return_value = chunk_round_trip(src, (uint32_t)size, model, up_model, cmp_data, |
80 | 2.70k | cmp_data_capacity, cmp_par_ptr, |
81 | 2.70k | use_decmp_buf, use_decmp_up_model); |
82 | 2.70k | switch (cmp_get_error_code(return_value)) { |
83 | 1.65k | case CMP_ERROR_NO_ERROR: |
84 | 1.65k | case CMP_ERROR_GENERIC: |
85 | 1.88k | case CMP_ERROR_SMALL_BUFFER: |
86 | | /* compression parameter errors */ |
87 | 1.89k | case CMP_ERROR_PAR_GENERIC: |
88 | 1.92k | case CMP_ERROR_PAR_SPECIFIC: |
89 | 1.92k | case CMP_ERROR_PAR_BUFFERS: |
90 | 2.06k | case CMP_ERROR_PAR_NULL: |
91 | 2.06k | case CMP_ERROR_PAR_NO_MODEL: |
92 | | /* chunk errors */ |
93 | 2.06k | case CMP_ERROR_CHUNK_NULL: |
94 | 2.06k | case CMP_ERROR_CHUNK_TOO_LARGE: |
95 | 2.06k | case CMP_ERROR_CHUNK_TOO_SMALL: |
96 | 2.24k | case CMP_ERROR_CHUNK_SIZE_INCONSISTENT: |
97 | 2.47k | case CMP_ERROR_CHUNK_SUBSERVICE_INCONSISTENT: |
98 | | /* collection errors */ |
99 | 2.47k | case CMP_ERROR_COL_SUBSERVICE_UNSUPPORTED: |
100 | 2.47k | case CMP_ERROR_COL_SIZE_INCONSISTENT: |
101 | 2.47k | break; |
102 | | /* compression entity errors */ |
103 | 0 | case CMP_ERROR_ENTITY_NULL: |
104 | 0 | FUZZ_ASSERT(0); |
105 | 0 | case CMP_ERROR_ENTITY_TOO_SMALL: |
106 | 0 | FUZZ_ASSERT(0); |
107 | 230 | case CMP_ERROR_ENTITY_HEADER: |
108 | 230 | break; |
109 | 0 | case CMP_ERROR_ENTITY_TIMESTAMP: |
110 | 0 | FUZZ_ASSERT(0); |
111 | | /* internal compressor errors */ |
112 | 0 | case CMP_ERROR_INT_DECODER: |
113 | 0 | FUZZ_ASSERT(0); |
114 | 0 | case CMP_ERROR_INT_DATA_TYPE_UNSUPPORTED: |
115 | 0 | FUZZ_ASSERT(0); |
116 | 0 | case CMP_ERROR_INT_CMP_COL_TOO_LARGE: |
117 | 0 | FUZZ_ASSERT(0); |
118 | |
|
119 | 0 | case CMP_ERROR_DATA_VALUE_TOO_LARGE: |
120 | 0 | FUZZ_ASSERT(0); |
121 | 0 | default: |
122 | 0 | FUZZ_ASSERT(0); |
123 | 2.70k | } |
124 | | |
125 | 2.70k | free(up_model); |
126 | 2.70k | free(cmp_data); |
127 | 2.70k | FUZZ_dataProducer_free(producer); |
128 | | |
129 | 2.70k | return 0; |
130 | 2.70k | } |