/src/net-snmp/testing/fuzzing/snmp_print_var_fuzzer.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021, Net-snmp authors |
3 | | * All rights reserved. |
4 | | * |
5 | | * Redistribution and use in source and binary forms, with or without |
6 | | * modification, are permitted provided that the following conditions are met: |
7 | | * |
8 | | * * Redistributions of source code must retain the above copyright notice, this |
9 | | * list of conditions and the following disclaimer. |
10 | | * |
11 | | * * Redistributions in binary form must reproduce the above copyright notice, |
12 | | * this list of conditions and the following disclaimer in the documentation |
13 | | * and/or other materials provided with the distribution. |
14 | | * |
15 | | * * Neither the name of the copyright holder nor the names of its |
16 | | * contributors may be used to endorse or promote products derived from |
17 | | * this software without specific prior written permission. |
18 | | * |
19 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
20 | | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
22 | | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
23 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
25 | | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
26 | | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
27 | | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 | | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | | */ |
30 | | |
31 | | #ifndef _GNU_SOURCE |
32 | | #define _GNU_SOURCE |
33 | | #endif |
34 | | |
35 | | #include <net-snmp/net-snmp-config.h> |
36 | | #include <net-snmp/net-snmp-includes.h> |
37 | | #include <stddef.h> |
38 | | #include <stdint.h> |
39 | | #include <stdlib.h> |
40 | | #include <unistd.h> |
41 | | |
42 | | #include "ada_fuzz_header.h" |
43 | | |
44 | | int |
45 | | LLVMFuzzerInitialize(int *argc, char ***argv) |
46 | 32 | { |
47 | 32 | if (getenv("NETSNMP_DEBUGGING") != NULL) { |
48 | | /* |
49 | | * Turn on all debugging, to help understand what |
50 | | * bits of the parser are running. |
51 | | */ |
52 | 0 | snmp_enable_stderrlog(); |
53 | 0 | snmp_set_do_debugging(1); |
54 | 0 | debug_register_tokens(""); |
55 | 0 | } |
56 | | |
57 | 32 | netsnmp_init_mib(); |
58 | | |
59 | 32 | return 0; |
60 | 32 | } |
61 | | |
62 | | int |
63 | | LLVMFuzzerTestOneInput(const uint8_t * data, size_t size) |
64 | 1.12k | { |
65 | 1.12k | af_gb_init(); |
66 | 1.12k | const uint8_t *data2 = data; |
67 | 1.12k | size_t size2 = size; |
68 | | |
69 | 1.12k | oid objid[MAX_OID_LEN]; |
70 | 1.12k | size_t objidlen = MAX_OID_LEN; |
71 | 1.12k | netsnmp_variable_list variable = { }; |
72 | | |
73 | | |
74 | | /* |
75 | | * Randomize a set of global variables |
76 | | */ |
77 | 1.12k | netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, |
78 | 1.12k | NETSNMP_DS_LIB_NUMERIC_TIMETICKS, |
79 | 1.12k | af_get_short(&data2, &size2)); |
80 | 1.12k | netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, |
81 | 1.12k | NETSNMP_DS_LIB_QUICKE_PRINT, |
82 | 1.12k | af_get_short(&data2, &size2)); |
83 | 1.12k | netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, |
84 | 1.12k | NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, |
85 | 1.12k | af_get_short(&data2, &size2)); |
86 | 1.12k | netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, |
87 | 1.12k | NETSNMP_DS_LIB_READ_UCD_STYLE_OID, |
88 | 1.12k | af_get_short(&data2, &size2)); |
89 | 1.12k | netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, |
90 | 1.12k | NETSNMP_DS_LIB_PRINT_BARE_VALUE, |
91 | 1.12k | af_get_short(&data2, &size2)); |
92 | 1.12k | netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, |
93 | 1.12k | NETSNMP_DS_LIB_DONT_PRINT_UNITS, |
94 | 1.12k | af_get_short(&data2, &size2)); |
95 | 1.12k | netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, |
96 | 1.12k | NETSNMP_DS_LIB_NO_DISPLAY_HINT, |
97 | 1.12k | af_get_short(&data2, &size2)); |
98 | 1.12k | netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, |
99 | 1.12k | NETSNMP_DS_LIB_ESCAPE_QUOTES, |
100 | 1.12k | af_get_short(&data2, &size2)); |
101 | | |
102 | | /* |
103 | | * Create three random strings based on fuzz data |
104 | | */ |
105 | 1.12k | char *s1 = af_gb_get_null_terminated(&data2, &size2); |
106 | 1.12k | char *s2 = af_gb_get_null_terminated(&data2, &size2); |
107 | 1.12k | char *s3 = af_gb_get_null_terminated(&data2, &size2); |
108 | 1.12k | if (!s1 || !s2 || !s3) { |
109 | 65 | af_gb_cleanup(); |
110 | 65 | return 0; |
111 | 65 | } |
112 | | |
113 | 1.06k | objidlen = MAX_OID_LEN; |
114 | 1.06k | if (read_objid(s1, objid, &objidlen) == 0) { |
115 | 548 | af_gb_cleanup(); |
116 | 548 | return 0; |
117 | 548 | } |
118 | | |
119 | | /* |
120 | | * Fuzz print_* functions |
121 | | */ |
122 | 516 | short decider = af_get_short(&data2, &size2); |
123 | 516 | switch (decider % 14) { |
124 | 181 | case 0:{ |
125 | 181 | variable.type = ASN_INTEGER; |
126 | 181 | long value = 3; |
127 | 181 | variable.val.integer = &value; |
128 | 181 | variable.val_len = 4; |
129 | 181 | variable.next_variable = NULL; |
130 | 181 | print_variable(objid, objidlen, &variable); |
131 | 181 | } |
132 | 181 | break; |
133 | 16 | case 1:{ |
134 | 16 | variable.type = ASN_IPADDRESS; |
135 | 16 | variable.val.string = (u_char *) s2; |
136 | 16 | variable.val_len = strlen(s2); |
137 | 16 | variable.next_variable = NULL; |
138 | 16 | print_variable(objid, objidlen, &variable); |
139 | 16 | } |
140 | 16 | break; |
141 | 33 | case 2:{ |
142 | 33 | variable.type = ASN_BIT_STR; |
143 | 33 | variable.val.string = (u_char *) s2; |
144 | 33 | variable.val_len = strlen(s2); |
145 | 33 | variable.next_variable = NULL; |
146 | 33 | print_variable(objid, objidlen, &variable); |
147 | 33 | } |
148 | 33 | break; |
149 | 31 | case 3:{ |
150 | 31 | variable.type = ASN_OPAQUE; |
151 | 31 | variable.val.string = (u_char *) s2; |
152 | 31 | variable.val_len = strlen(s2); |
153 | 31 | variable.next_variable = NULL; |
154 | 31 | print_variable(objid, objidlen, &variable); |
155 | 31 | } |
156 | 31 | break; |
157 | 163 | case 4:{ |
158 | 163 | variable.type = ASN_OCTET_STR; |
159 | 163 | variable.val.string = (u_char *) s2; |
160 | 163 | variable.val_len = strlen(s2); |
161 | 163 | variable.next_variable = NULL; |
162 | 163 | print_variable(objid, objidlen, &variable); |
163 | 163 | } |
164 | 163 | break; |
165 | 6 | case 5:{ |
166 | 6 | variable.type = ASN_GAUGE; |
167 | 6 | long value = 3; |
168 | 6 | variable.val.integer = &value; |
169 | 6 | variable.val_len = 4; |
170 | 6 | variable.next_variable = NULL; |
171 | 6 | print_variable(objid, objidlen, &variable); |
172 | 6 | } |
173 | 6 | break; |
174 | 3 | case 6:{ |
175 | 3 | variable.type = ASN_COUNTER64; |
176 | 3 | struct counter64 c64; |
177 | 3 | c64.low = 0; |
178 | 3 | c64.high = 1; |
179 | 3 | variable.val.counter64 = &c64; |
180 | 3 | variable.val_len = 1; |
181 | 3 | variable.next_variable = NULL; |
182 | 3 | print_variable(objid, objidlen, &variable); |
183 | 3 | } |
184 | 3 | break; |
185 | 14 | case 7:{ |
186 | 14 | variable.type = ASN_TIMETICKS; |
187 | 14 | long value = 3; |
188 | 14 | variable.val.integer = &value; |
189 | 14 | variable.val_len = 4; |
190 | 14 | variable.next_variable = NULL; |
191 | 14 | print_variable(objid, objidlen, &variable); |
192 | 14 | } |
193 | 14 | break; |
194 | 11 | case 8:{ |
195 | 11 | variable.type = ASN_OBJECT_ID; |
196 | 11 | variable.val.objid = (oid *) s2; |
197 | 11 | variable.val_len = strlen(s2); |
198 | 11 | variable.next_variable = NULL; |
199 | 11 | print_variable(objid, objidlen, &variable); |
200 | 11 | } |
201 | 11 | break; |
202 | 11 | case 9:{ |
203 | 11 | variable.type = ASN_COUNTER; |
204 | 11 | long value = 3; |
205 | 11 | variable.val.integer = &value; |
206 | 11 | variable.next_variable = NULL; |
207 | 11 | print_variable(objid, objidlen, &variable); |
208 | 11 | } |
209 | 11 | break; |
210 | 7 | case 10:{ |
211 | 7 | variable.type = ASN_UINTEGER; |
212 | 7 | long value = 3; |
213 | 7 | variable.val.integer = &value; |
214 | 7 | variable.next_variable = NULL; |
215 | 7 | print_variable(objid, objidlen, &variable); |
216 | 7 | } |
217 | 7 | break; |
218 | 11 | case 11:{ |
219 | 11 | variable.type = ASN_OPAQUE_DOUBLE; |
220 | 11 | double value = 3.3; |
221 | 11 | variable.val.doubleVal = &value; |
222 | 11 | variable.next_variable = NULL; |
223 | 11 | print_variable(objid, objidlen, &variable); |
224 | 11 | } |
225 | 11 | break; |
226 | 22 | case 12:{ |
227 | 22 | variable.type = ASN_OPAQUE_FLOAT; |
228 | 22 | float fVal = 3.3; |
229 | 22 | variable.val.floatVal = &fVal; |
230 | 22 | variable.next_variable = NULL; |
231 | 22 | print_variable(objid, objidlen, &variable); |
232 | 22 | } |
233 | 22 | break; |
234 | 7 | case 13:{ |
235 | 7 | variable.type = ASN_NULL; |
236 | 7 | variable.next_variable = NULL; |
237 | 7 | print_variable(objid, objidlen, &variable); |
238 | 7 | } |
239 | 7 | break; |
240 | 0 | default: |
241 | 0 | break; |
242 | 516 | } |
243 | | |
244 | | /* |
245 | | * Fuzz snprint_* functions |
246 | | */ |
247 | 516 | char *snprint_hints = |
248 | 516 | af_gb_get_null_terminated(&data2, &size2); |
249 | 516 | if (!snprint_hints) { |
250 | 289 | af_gb_cleanup(); |
251 | 289 | return 0; |
252 | 289 | } |
253 | | /* |
254 | | * Avoid any p's and n's and s's in hints section, as |
255 | | * realloc_* functions will use the hints argument in a sprintf |
256 | | * call, which will interpret the variables value as a pointer. |
257 | | * Adjusting the fuzzers input-space according to meet the preconditions |
258 | | * of these functions. |
259 | | */ |
260 | 9.25k | for (size_t i = 0; i < strlen(snprint_hints); i++) { |
261 | 9.03k | if (snprint_hints[i] == 'p' || snprint_hints[i] == 'n' |
262 | 8.79k | || snprint_hints[i] == 's' || snprint_hints[i] == 'S') { |
263 | 520 | snprint_hints[i] = 'o'; |
264 | 520 | } |
265 | 9.03k | } |
266 | | |
267 | 227 | variable.type = ASN_INTEGER; |
268 | 227 | long value1 = 3; |
269 | 227 | variable.val.integer = &value1; |
270 | 227 | variable.val_len = 4; |
271 | 227 | variable.next_variable = NULL; |
272 | 227 | char out_buf[100]; |
273 | 227 | snprint_integer(out_buf, 100, &variable, NULL, snprint_hints, s3); |
274 | | |
275 | 227 | variable.type = ASN_UINTEGER; |
276 | 227 | long value2 = 3; |
277 | 227 | variable.val.integer = &value2; |
278 | 227 | variable.val_len = 4; |
279 | 227 | variable.next_variable = NULL; |
280 | 227 | char out_buf2[100]; |
281 | 227 | snprint_uinteger(out_buf2, 100, &variable, NULL, snprint_hints, s3); |
282 | | |
283 | | /* |
284 | | * Free fuzz data |
285 | | */ |
286 | 227 | af_gb_cleanup(); |
287 | 227 | return 0; |
288 | 516 | } |