/src/cmp_tool/test/fuzz/fuzz_cmp_tool.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * @file fuzz_cmp_tool.c |
3 | | * @date 2025 |
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 <limits.h> |
25 | | #include <stdint.h> |
26 | | #include <stdint.h> |
27 | | #include <stddef.h> |
28 | | #include <string.h> |
29 | | |
30 | | #include "fuzz_helpers.h" |
31 | | #include "fuzz_data_producer.h" |
32 | | |
33 | 1.79k | #define MAX_ARG_COUNT 32 |
34 | 3.51k | #define MAX_ARG_SIZE 64 |
35 | | |
36 | | |
37 | | int testable_cmp_tool_main(int argc, char **argv); |
38 | | |
39 | | |
40 | | static void add_argument_with_file(char **argv, int index, const char *flag, const char *file) |
41 | 6.27k | { |
42 | 6.27k | if (index > 0) { /* zero is revert for program name */ |
43 | 6.01k | size_t flag_len = strlen(flag); |
44 | 6.01k | size_t file_len = strlen(file); |
45 | | |
46 | 6.01k | FUZZ_ASSERT(flag_len + file_len < MAX_ARG_SIZE); |
47 | 6.01k | memcpy(argv[index], flag, flag_len); |
48 | 6.01k | memcpy(argv[index]+flag_len, file, file_len + 1); |
49 | 6.01k | } |
50 | 6.27k | } |
51 | | |
52 | | |
53 | | static int gen_argv(FUZZ_dataProducer_t *producer, char **argv, const char *data_file, |
54 | | const char *model_file, const char *cfg_file, const char *info_file, |
55 | | const uint8_t *other_arguments, size_t o_args_size) |
56 | 1.75k | { |
57 | 1.75k | int argc = FUZZ_dataProducer_int32Range(producer, 1, MAX_ARG_COUNT); |
58 | 1.75k | int i, end; |
59 | | |
60 | | /* Add optional arguments no the end so they have higher priority */ |
61 | 1.75k | end = argc-1; |
62 | | /* TODO: How to clean up written stuff by the cmp_tool? */ |
63 | 1.75k | add_argument_with_file(argv, end--, "-o", FUZZ_TMP_DIR "/fuzz-output-cmp_tool"); |
64 | 1.75k | if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) |
65 | 1.55k | add_argument_with_file(argv, end--, "-d", data_file); |
66 | 1.75k | if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) |
67 | 848 | add_argument_with_file(argv, end--, "-m", model_file); |
68 | 1.75k | if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) |
69 | 1.14k | add_argument_with_file(argv, end--, "-c", cfg_file); |
70 | 1.75k | if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) |
71 | 963 | add_argument_with_file(argv, end--, "-i", info_file); |
72 | | |
73 | 5.24k | for (i = 0; i < end; i++) { |
74 | 3.48k | size_t s = FUZZ_dataProducer_uint32Range(producer, 0, MAX_ARG_SIZE-1); |
75 | | |
76 | 3.48k | if (s > o_args_size) |
77 | 866 | s = o_args_size; |
78 | 3.48k | memcpy(argv[i], other_arguments, s); |
79 | 3.48k | argv[i][s] = '\0'; |
80 | 3.48k | other_arguments += s; |
81 | 3.48k | o_args_size -= s; |
82 | 3.48k | } |
83 | | |
84 | 1.75k | return argc; |
85 | 1.75k | } |
86 | | |
87 | | |
88 | | |
89 | | static char *get_file(FUZZ_dataProducer_t *producer, const uint8_t **src, uint32_t *size) |
90 | 7.02k | { |
91 | 7.02k | uint32_t file_size = FUZZ_dataProducer_uint32Range(producer, 0, *size); |
92 | 7.02k | char *file = FUZZ_buf_to_file(*src, file_size); |
93 | 7.02k | *src += file_size; |
94 | 7.02k | *size -= file_size; |
95 | 7.02k | return file; |
96 | 7.02k | } |
97 | | |
98 | | |
99 | | int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) |
100 | 1.75k | { |
101 | 1.75k | static char **argv; |
102 | | /* |
103 | | * Give a random portion of src data to the producer, to use for |
104 | | * parameter generation. The rest will be used for the file content and |
105 | | * arguments |
106 | | */ |
107 | 1.75k | FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size); |
108 | 1.75k | uint32_t size32 = (uint32_t)FUZZ_dataProducer_reserveDataPrefix(producer); |
109 | 1.75k | const char *data_file = get_file(producer, &src, &size32); |
110 | 1.75k | const char *model_file = get_file(producer, &src, &size32); |
111 | 1.75k | const char *info_file = get_file(producer, &src, &size32); |
112 | 1.75k | const char *cfg_file = get_file(producer, &src, &size32); |
113 | 1.75k | const uint8_t *other_arguments = src; |
114 | | |
115 | 1.75k | int argc; |
116 | | |
117 | 1.75k | FUZZ_ASSERT(size < UINT32_MAX); |
118 | | |
119 | 1.75k | if (argv == NULL) { |
120 | 1 | static const char program_name[] = "cmp_tool_fuzz"; |
121 | 1 | char *data; |
122 | 1 | size_t i; |
123 | | |
124 | 1 | argv = FUZZ_malloc(sizeof(*argv) * MAX_ARG_COUNT); |
125 | 1 | data = FUZZ_malloc(sizeof(*data) * MAX_ARG_COUNT * MAX_ARG_SIZE); |
126 | 1 | memset(data, 0, sizeof(*data) * MAX_ARG_COUNT * MAX_ARG_SIZE); |
127 | 33 | for (i = 0; i < MAX_ARG_COUNT; i++) |
128 | 32 | argv[i] = &data[i*MAX_ARG_SIZE]; |
129 | | |
130 | 1 | FUZZ_ASSERT(sizeof(program_name) <= MAX_ARG_SIZE); |
131 | 1 | memcpy(argv[0], program_name, sizeof(program_name)); |
132 | 1 | } |
133 | | |
134 | 0 | argc = gen_argv(producer, argv, data_file, model_file, cfg_file, |
135 | 1.75k | info_file, other_arguments, size32); |
136 | | |
137 | | /* for(int i = 1; i < argc; i++) */ |
138 | | /* printf("%s\n", argv[i]); */ |
139 | | |
140 | 1.75k | testable_cmp_tool_main(argc, argv); |
141 | | |
142 | 1.75k | FUZZ_delete_file(data_file); |
143 | 1.75k | FUZZ_delete_file(model_file); |
144 | 1.75k | FUZZ_delete_file(info_file); |
145 | 1.75k | FUZZ_delete_file(cfg_file); |
146 | | |
147 | 1.75k | FUZZ_dataProducer_free(producer); |
148 | | |
149 | 1.75k | return 0; |
150 | 1.75k | } |