Coverage Report

Created: 2026-01-10 06:37

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