Coverage Report

Created: 2026-08-13 09:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
31
{
47
31
    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
31
    netsnmp_init_mib();
58
59
31
    return 0;
60
31
}
61
62
int
63
LLVMFuzzerTestOneInput(const uint8_t * data, size_t size)
64
1.16k
{
65
1.16k
    af_gb_init();
66
1.16k
    const uint8_t  *data2 = data;
67
1.16k
    size_t          size2 = size;
68
69
1.16k
    oid             objid[MAX_OID_LEN];
70
1.16k
    size_t          objidlen = MAX_OID_LEN;
71
1.16k
    netsnmp_variable_list variable = { };
72
73
74
    /*
75
     * Randomize a set of global variables
76
     */
77
1.16k
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
78
1.16k
                           NETSNMP_DS_LIB_NUMERIC_TIMETICKS,
79
1.16k
                           af_get_short(&data2, &size2));
80
1.16k
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
81
1.16k
                           NETSNMP_DS_LIB_QUICKE_PRINT,
82
1.16k
                           af_get_short(&data2, &size2));
83
1.16k
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
84
1.16k
                           NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM,
85
1.16k
                           af_get_short(&data2, &size2));
86
1.16k
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
87
1.16k
                           NETSNMP_DS_LIB_READ_UCD_STYLE_OID,
88
1.16k
                           af_get_short(&data2, &size2));
89
1.16k
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
90
1.16k
                           NETSNMP_DS_LIB_PRINT_BARE_VALUE,
91
1.16k
                           af_get_short(&data2, &size2));
92
1.16k
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
93
1.16k
                           NETSNMP_DS_LIB_DONT_PRINT_UNITS,
94
1.16k
                           af_get_short(&data2, &size2));
95
1.16k
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
96
1.16k
                           NETSNMP_DS_LIB_NO_DISPLAY_HINT,
97
1.16k
                           af_get_short(&data2, &size2));
98
1.16k
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
99
1.16k
                           NETSNMP_DS_LIB_ESCAPE_QUOTES,
100
1.16k
                           af_get_short(&data2, &size2));
101
102
    /*
103
     * Create three random strings based on fuzz data
104
     */
105
1.16k
    char           *s1 = af_gb_get_null_terminated(&data2, &size2);
106
1.16k
    char           *s2 = af_gb_get_null_terminated(&data2, &size2);
107
1.16k
    char           *s3 = af_gb_get_null_terminated(&data2, &size2);
108
1.16k
    if (!s1 || !s2 || !s3) {
109
66
        af_gb_cleanup();
110
66
        return 0;
111
66
    }
112
113
1.09k
    objidlen = MAX_OID_LEN;
114
1.09k
    if (read_objid(s1, objid, &objidlen) == 0) {
115
555
        af_gb_cleanup();
116
555
        return 0;
117
555
    }
118
119
    /*
120
     * Fuzz print_* functions
121
     */
122
540
    short           decider = af_get_short(&data2, &size2);
123
540
    switch (decider % 14) {
124
192
    case 0:{
125
192
            variable.type = ASN_INTEGER;
126
192
            long            value = 3;
127
192
            variable.val.integer = &value;
128
192
            variable.val_len = 4;
129
192
            variable.next_variable = NULL;
130
192
            print_variable(objid, objidlen, &variable);
131
192
        }
132
192
        break;
133
27
    case 1:{
134
27
            variable.type = ASN_IPADDRESS;
135
27
            variable.val.string = (u_char *) s2;
136
27
            variable.val_len = strlen(s2);
137
27
            variable.next_variable = NULL;
138
27
            print_variable(objid, objidlen, &variable);
139
27
        }
140
27
        break;
141
39
    case 2:{
142
39
            variable.type = ASN_BIT_STR;
143
39
            variable.val.string = (u_char *) s2;
144
39
            variable.val_len = strlen(s2);
145
39
            variable.next_variable = NULL;
146
39
            print_variable(objid, objidlen, &variable);
147
39
        }
148
39
        break;
149
16
    case 3:{
150
16
            variable.type = ASN_OPAQUE;
151
16
            variable.val.string = (u_char *) s2;
152
16
            variable.val_len = strlen(s2);
153
16
            variable.next_variable = NULL;
154
16
            print_variable(objid, objidlen, &variable);
155
16
        }
156
16
        break;
157
174
    case 4:{
158
174
            variable.type = ASN_OCTET_STR;
159
174
            variable.val.string = (u_char *) s2;
160
174
            variable.val_len = strlen(s2);
161
174
            variable.next_variable = NULL;
162
174
            print_variable(objid, objidlen, &variable);
163
174
        }
164
174
        break;
165
7
    case 5:{
166
7
            variable.type = ASN_GAUGE;
167
7
            long            value = 3;
168
7
            variable.val.integer = &value;
169
7
            variable.val_len = 4;
170
7
            variable.next_variable = NULL;
171
7
            print_variable(objid, objidlen, &variable);
172
7
        }
173
7
        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
9
    case 7:{
186
9
            variable.type = ASN_TIMETICKS;
187
9
            long            value = 3;
188
9
            variable.val.integer = &value;
189
9
            variable.val_len = 4;
190
9
            variable.next_variable = NULL;
191
9
            print_variable(objid, objidlen, &variable);
192
9
        }
193
9
        break;
194
17
    case 8:{
195
17
            variable.type = ASN_OBJECT_ID;
196
17
            variable.val.objid = (oid *) s2;
197
17
            variable.val_len = strlen(s2);
198
17
            variable.next_variable = NULL;
199
17
            print_variable(objid, objidlen, &variable);
200
17
        }
201
17
        break;
202
6
    case 9:{
203
6
            variable.type = ASN_COUNTER;
204
6
            long            value = 3;
205
6
            variable.val.integer = &value;
206
6
            variable.next_variable = NULL;
207
6
            print_variable(objid, objidlen, &variable);
208
6
        }
209
6
        break;
210
6
    case 10:{
211
6
            variable.type = ASN_UINTEGER;
212
6
            long            value = 3;
213
6
            variable.val.integer = &value;
214
6
            variable.next_variable = NULL;
215
6
            print_variable(objid, objidlen, &variable);
216
6
        }
217
6
        break;
218
16
    case 11:{
219
16
            variable.type = ASN_OPAQUE_DOUBLE;
220
16
            double          value = 3.3;
221
16
            variable.val.doubleVal = &value;
222
16
            variable.next_variable = NULL;
223
16
            print_variable(objid, objidlen, &variable);
224
16
        }
225
16
        break;
226
24
    case 12:{
227
24
            variable.type = ASN_OPAQUE_FLOAT;
228
24
            float           fVal = 3.3;
229
24
            variable.val.floatVal = &fVal;
230
24
            variable.next_variable = NULL;
231
24
            print_variable(objid, objidlen, &variable);
232
24
        }
233
24
        break;
234
4
    case 13:{
235
4
            variable.type = ASN_NULL;
236
4
            variable.next_variable = NULL;
237
4
            print_variable(objid, objidlen, &variable);
238
4
        }
239
4
        break;
240
0
    default:
241
0
        break;
242
540
    }
243
244
    /*
245
     * Fuzz snprint_* functions
246
     */
247
540
    char           *snprint_hints =
248
540
        af_gb_get_null_terminated(&data2, &size2);
249
540
    if (!snprint_hints) {
250
295
        af_gb_cleanup();
251
295
        return 0;
252
295
    }
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
7.97k
    for (size_t i = 0; i < strlen(snprint_hints); i++) {
261
7.73k
        if (snprint_hints[i] == 'p' || snprint_hints[i] == 'n'
262
7.51k
            || snprint_hints[i] == 's' || snprint_hints[i] == 'S') {
263
434
            snprint_hints[i] = 'o';
264
434
        }
265
7.73k
    }
266
267
245
    variable.type = ASN_INTEGER;
268
245
    long            value1 = 3;
269
245
    variable.val.integer = &value1;
270
245
    variable.val_len = 4;
271
245
    variable.next_variable = NULL;
272
245
    char            out_buf[100];
273
245
    snprint_integer(out_buf, 100, &variable, NULL, snprint_hints, s3);
274
275
245
    variable.type = ASN_UINTEGER;
276
245
    long            value2 = 3;
277
245
    variable.val.integer = &value2;
278
245
    variable.val_len = 4;
279
245
    variable.next_variable = NULL;
280
245
    char            out_buf2[100];
281
245
    snprint_uinteger(out_buf2, 100, &variable, NULL, snprint_hints, s3);
282
283
    /*
284
     * Free fuzz data
285
     */
286
245
    af_gb_cleanup();
287
245
    return 0;
288
540
}