Skip to content

Commit a9ddcd6

Browse files
arthurscchanalandekok
authored andcommitted
oss-fuzz: Add new fuzzer targetting base16/32/64 encode/decode
Signed-off-by: Arthur Chan <arthur.chan@adalogics.com> With manual merges for new location of the fuzzer
1 parent 8d3c5e3 commit a9ddcd6

3 files changed

Lines changed: 143 additions & 2 deletions

File tree

src/fuzzer/all.mk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ FUZZER_PROTOCOLS = radius dhcpv4 dhcpv6 dns tacacs vmps tftp bfd cbor der arp
1515
# as a wire protocol (see src/lib/util/fuzzer.c) but isn't itself
1616
# a network protocol, so it lives here too.
1717
#
18-
FUZZER_NON_PROTOCOL_TARGETS = util json value cf xlat
18+
FUZZER_NON_PROTOCOL_TARGETS = util json value cf xlat fuzzer_base16_32_64
1919

2020
#
2121
# Build these fuzzers, but skip them in CI.
@@ -69,7 +69,7 @@ clean: clean.fuzzer
6969
#
7070
# Standalone fuzzers' build mks
7171
#
72-
SUBMAKEFILES += fuzzer_json.mk fuzzer_value.mk fuzzer_xlat.mk fuzzer_cf.mk
72+
SUBMAKEFILES += fuzzer_json.mk fuzzer_value.mk fuzzer_xlat.mk fuzzer_cf.mk fuzzer_base16_32_64.mk
7373

7474
# fuzzer_cf.mk
7575

src/fuzzer/fuzzer_base16_32_64.c

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* This program is free software; you can redistribute it and/or modify
3+
* it under the terms of the GNU General Public License as published by
4+
* the Free Software Foundation; either version 2 of the License, or
5+
* (at your option) any later version.
6+
*
7+
* This program is distributed in the hope that it will be useful,
8+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
* GNU General Public License for more details.
11+
*/
12+
13+
/**
14+
* @file src/fuzzer/fuzzer_base16_32_64.c
15+
* @brief Fuzz the base conversion functions
16+
*/
17+
RCSID("$Id$")
18+
19+
#include <freeradius-devel/util/base16.h>
20+
#include <freeradius-devel/util/base32.h>
21+
#include <freeradius-devel/util/base64.h>
22+
#include <freeradius-devel/util/dbuff.h>
23+
#include <freeradius-devel/util/sbuff.h>
24+
25+
int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len);
26+
27+
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
28+
{
29+
if (size == 0) return 0;
30+
31+
uint8_t decoded[4096];
32+
char encoded[8192];
33+
34+
fr_dbuff_t decode_dbuff, input_dbuff;
35+
fr_sbuff_t encode_sbuff, input_sbuff;
36+
fr_sbuff_parse_error_t err;
37+
38+
/*
39+
* BASE64 TESTS (4 variants)
40+
* Vulnerable: fr_base64_alphabet_decode[UINT8_MAX] - off-by-one error
41+
*/
42+
43+
// Test 1: Decode with standard base64 alphabet
44+
fr_sbuff_init_in(&input_sbuff, (char const *)data, size);
45+
fr_dbuff_init(&decode_dbuff, decoded, sizeof(decoded));
46+
(void)fr_base64_decode_nstd(&err, &decode_dbuff, &input_sbuff,
47+
true, true, fr_base64_alphabet_decode);
48+
49+
// Test 2: Decode with URL-safe base64 alphabet
50+
fr_sbuff_init_in(&input_sbuff, (char const *)data, size);
51+
fr_dbuff_init(&decode_dbuff, decoded, sizeof(decoded));
52+
(void)fr_base64_decode_nstd(&err, &decode_dbuff, &input_sbuff,
53+
false, false, fr_base64_url_alphabet_decode);
54+
55+
// Test 3: Encode with standard base64 alphabet (limit input size)
56+
if (size <= 2048) {
57+
fr_dbuff_init(&input_dbuff, data, size);
58+
fr_sbuff_init_out(&encode_sbuff, encoded, sizeof(encoded));
59+
(void)fr_base64_encode_nstd(&encode_sbuff, &input_dbuff,
60+
true, fr_base64_alphabet_encode);
61+
}
62+
63+
// Test 4: Encode with URL-safe base64 alphabet (limit input size)
64+
if (size <= 2048) {
65+
fr_dbuff_init(&input_dbuff, data, size);
66+
fr_sbuff_init_out(&encode_sbuff, encoded, sizeof(encoded));
67+
(void)fr_base64_encode_nstd(&encode_sbuff, &input_dbuff,
68+
false, fr_base64_url_alphabet_encode);
69+
}
70+
71+
/*
72+
* BASE32 TESTS (4 variants)
73+
* Vulnerable: fr_base32_alphabet_decode[UINT8_MAX] - off-by-one error
74+
*/
75+
76+
// Test 5: Decode with standard base32 alphabet
77+
fr_sbuff_init_in(&input_sbuff, (char const *)data, size);
78+
fr_dbuff_init(&decode_dbuff, decoded, sizeof(decoded));
79+
(void)fr_base32_decode_nstd(&err, &decode_dbuff, &input_sbuff,
80+
true, true, fr_base32_alphabet_decode);
81+
82+
// Test 6: Decode with base32hex alphabet
83+
fr_sbuff_init_in(&input_sbuff, (char const *)data, size);
84+
fr_dbuff_init(&decode_dbuff, decoded, sizeof(decoded));
85+
(void)fr_base32_decode_nstd(&err, &decode_dbuff, &input_sbuff,
86+
false, false, fr_base32_hex_alphabet_decode);
87+
88+
// Test 7: Encode with standard base32 alphabet (limit input size)
89+
if (size <= 2048) {
90+
fr_dbuff_init(&input_dbuff, data, size);
91+
fr_sbuff_init_out(&encode_sbuff, encoded, sizeof(encoded));
92+
(void)fr_base32_encode_nstd(&encode_sbuff, &input_dbuff,
93+
true, fr_base32_alphabet_encode);
94+
}
95+
96+
// Test 8: Encode with base32hex alphabet (limit input size)
97+
if (size <= 2048) {
98+
fr_dbuff_init(&input_dbuff, data, size);
99+
fr_sbuff_init_out(&encode_sbuff, encoded, sizeof(encoded));
100+
(void)fr_base32_encode_nstd(&encode_sbuff, &input_dbuff,
101+
false, fr_base32_hex_alphabet_encode);
102+
}
103+
104+
/*
105+
* BASE16 TESTS (3 variants)
106+
* NOT vulnerable: fr_base16_alphabet_decode_mc[UINT8_MAX + 1] - correct size!
107+
* Testing to ensure the fix is correct and no regressions
108+
*/
109+
110+
// Test 9: Decode with mixed-case base16 alphabet
111+
fr_sbuff_init_in(&input_sbuff, (char const *)data, size);
112+
fr_dbuff_init(&decode_dbuff, decoded, sizeof(decoded));
113+
(void)fr_base16_decode_nstd(&err, &decode_dbuff, &input_sbuff,
114+
true, fr_base16_alphabet_decode_mc);
115+
116+
// Test 10: Encode with lowercase base16 alphabet (limit input size)
117+
if (size <= 2048) {
118+
fr_dbuff_init(&input_dbuff, data, size);
119+
fr_sbuff_init_out(&encode_sbuff, encoded, sizeof(encoded));
120+
(void)fr_base16_encode_nstd(&encode_sbuff, &input_dbuff,
121+
fr_base16_alphabet_encode_lc);
122+
}
123+
124+
// Test 11: Encode with uppercase base16 alphabet (limit input size)
125+
if (size <= 2048) {
126+
fr_dbuff_init(&input_dbuff, data, size);
127+
fr_sbuff_init_out(&encode_sbuff, encoded, sizeof(encoded));
128+
(void)fr_base16_encode_nstd(&encode_sbuff, &input_dbuff,
129+
fr_base16_alphabet_encode_uc);
130+
}
131+
132+
return 0;
133+
}

src/fuzzer/fuzzer_base16_32_64.mk

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
TARGET := fuzzer_base16_32_64$(E)
2+
SOURCES := fuzzer_base16_32_64.c
3+
4+
TGT_PREREQS := libfreeradius-util$(L)
5+
6+
SRC_CFLAGS := -fsanitize=fuzzer
7+
TGT_LDFLAGS := -fsanitize=fuzzer
8+
TGT_LDLIBS := $(LIBS)

0 commit comments

Comments
 (0)