Coverage Report

Created: 2026-03-31 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/kea-fuzzer/fuzz_encode.cc
Line
Count
Source
1
// Copyright (C) 2025 Ada Logics Ltd.
2
//
3
// This Source Code Form is subject to the terms of the Mozilla Public
4
// License, v. 2.0. If a copy of the MPL was not distributed with this
5
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
////////////////////////////////////////////////////////////////////////////////
7
#include <config.h>
8
#include <fuzzer/FuzzedDataProvider.h>
9
10
#include <exceptions/exceptions.h>
11
#include <util/encode/encode.h>
12
13
#include <string>
14
#include <vector>
15
#include <cstddef>
16
17
using namespace isc::util::encode;
18
19
1.34k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
20
1.34k
    if (size < 2) {
21
1
        return 0;
22
1
    }
23
24
1.34k
    FuzzedDataProvider fdp(data, size);
25
    
26
    // Choose which encoding/decoding path to test
27
1.34k
    uint8_t path = fdp.ConsumeIntegralInRange<uint8_t>(0, 11);
28
    
29
1.34k
    std::vector<uint8_t> binary_data;
30
1.34k
    std::string encoded_str;
31
1.34k
    std::vector<uint8_t> decoded_output;
32
    
33
1.34k
    switch (path) {
34
121
        case 0: {
35
            // Test Base64 encoding from binary data
36
121
            try {
37
121
                size_t bin_size = fdp.ConsumeIntegralInRange<size_t>(0, size);
38
121
                binary_data = fdp.ConsumeBytes<uint8_t>(bin_size);
39
121
                encoded_str = encodeBase64(binary_data);
40
                // Verify round-trip
41
121
                decodeBase64(encoded_str, decoded_output);
42
121
            } catch (const isc::Exception&) {
43
                // Expected for invalid input
44
0
            }
45
121
            break;
46
121
        }
47
        
48
102
        case 1: {
49
            // Test Base64 decoding from string
50
102
            try {
51
102
                encoded_str = fdp.ConsumeRemainingBytesAsString();
52
102
                decodeBase64(encoded_str, decoded_output);
53
102
            } catch (const isc::Exception&) {
54
                // Expected for invalid Base64 strings
55
100
            }
56
102
            break;
57
102
        }
58
        
59
95
        case 2: {
60
            // Test Base32Hex encoding from binary data
61
95
            try {
62
95
                size_t bin_size = fdp.ConsumeIntegralInRange<size_t>(0, size);
63
95
                binary_data = fdp.ConsumeBytes<uint8_t>(bin_size);
64
95
                encoded_str = encodeBase32Hex(binary_data);
65
                // Verify round-trip
66
95
                decodeBase32Hex(encoded_str, decoded_output);
67
95
            } catch (const isc::Exception&) {
68
                // Expected for invalid input
69
0
            }
70
95
            break;
71
95
        }
72
        
73
72
        case 3: {
74
            // Test Base32Hex decoding from string
75
72
            try {
76
72
                encoded_str = fdp.ConsumeRemainingBytesAsString();
77
72
                decodeBase32Hex(encoded_str, decoded_output);
78
72
            } catch (const isc::Exception&) {
79
                // Expected for invalid Base32Hex strings
80
70
            }
81
72
            break;
82
72
        }
83
        
84
109
        case 4: {
85
            // Test Base16 (hex) encoding from binary data
86
109
            try {
87
109
                size_t bin_size = fdp.ConsumeIntegralInRange<size_t>(0, size);
88
109
                binary_data = fdp.ConsumeBytes<uint8_t>(bin_size);
89
109
                encoded_str = encodeHex(binary_data);
90
                // Verify round-trip
91
109
                decodeHex(encoded_str, decoded_output);
92
109
            } catch (const isc::Exception&) {
93
                // Expected for invalid input
94
0
            }
95
109
            break;
96
109
        }
97
        
98
63
        case 5: {
99
            // Test Base16 (hex) decoding from string
100
63
            try {
101
63
                encoded_str = fdp.ConsumeRemainingBytesAsString();
102
63
                decodeHex(encoded_str, decoded_output);
103
63
            } catch (const isc::Exception&) {
104
                // Expected for invalid hex strings
105
61
            }
106
63
            break;
107
63
        }
108
        
109
142
        case 6: {
110
            // Test Base64 with various padding scenarios
111
142
            try {
112
142
                std::string test_str = fdp.ConsumeRandomLengthString();
113
                // Add various padding permutations
114
142
                test_str += fdp.ConsumeBool() ? "=" : "";
115
142
                test_str += fdp.ConsumeBool() ? "=" : "";
116
142
                decodeBase64(test_str, decoded_output);
117
142
            } catch (const isc::Exception&) {
118
                // Expected for invalid padding
119
100
            }
120
142
            break;
121
142
        }
122
        
123
133
        case 7: {
124
            // Test Base32Hex with various padding scenarios
125
133
            try {
126
133
                std::string test_str = fdp.ConsumeRandomLengthString();
127
                // Add various padding permutations
128
238
                for (int i = 0; i < fdp.ConsumeIntegralInRange(0, 6); i++) {
129
105
                    test_str += "=";
130
105
                }
131
133
                decodeBase32Hex(test_str, decoded_output);
132
133
            } catch (const isc::Exception&) {
133
                // Expected for invalid padding
134
112
            }
135
133
            break;
136
133
        }
137
        
138
68
        case 8: {
139
            // Test mixed case Base64 (should be case-sensitive)
140
68
            try {
141
68
                encoded_str = fdp.ConsumeRemainingBytesAsString();
142
                // Mix uppercase and lowercase
143
8.73M
                for (auto& c : encoded_str) {
144
8.73M
                    if (fdp.ConsumeBool() && isalpha(c)) {
145
0
                        c = (isupper(c)) ? tolower(c) : toupper(c);
146
0
                    }
147
8.73M
                }
148
68
                decodeBase64(encoded_str, decoded_output);
149
68
            } catch (const isc::Exception&) {
150
                // Expected for case errors
151
67
            }
152
68
            break;
153
68
        }
154
        
155
67
        case 9: {
156
            // Test mixed case Base32Hex (case-insensitive)
157
67
            try {
158
67
                encoded_str = fdp.ConsumeRemainingBytesAsString();
159
                // Mix uppercase and lowercase
160
7.01M
                for (auto& c : encoded_str) {
161
7.01M
                    if (fdp.ConsumeBool() && isalpha(c)) {
162
0
                        c = (isupper(c)) ? tolower(c) : toupper(c);
163
0
                    }
164
7.01M
                }
165
67
                decodeBase32Hex(encoded_str, decoded_output);
166
67
            } catch (const isc::Exception&) {
167
                // May succeed due to case-insensitivity
168
66
            }
169
67
            break;
170
67
        }
171
        
172
66
        case 10: {
173
            // Test Base16 with mixed case (case-insensitive)
174
66
            try {
175
66
                encoded_str = fdp.ConsumeRemainingBytesAsString();
176
                // Mix uppercase and lowercase
177
7.43M
                for (auto& c : encoded_str) {
178
7.43M
                    if (fdp.ConsumeBool() && isalpha(c)) {
179
0
                        c = (isupper(c)) ? tolower(c) : toupper(c);
180
0
                    }
181
7.43M
                }
182
66
                decodeHex(encoded_str, decoded_output);
183
66
            } catch (const isc::Exception&) {
184
                // May succeed due to case-insensitivity
185
64
            }
186
66
            break;
187
66
        }
188
        
189
309
        case 11: {
190
            // Test encoding/decoding with whitespace injection
191
309
            try {
192
309
                std::string test_str = fdp.ConsumeRandomLengthString();
193
                // Inject whitespace characters
194
309
                size_t insertions = fdp.ConsumeIntegralInRange<size_t>(0, 10);
195
1.34k
                for (size_t i = 0; i < insertions && test_str.size() > 0; i++) {
196
1.03k
                    size_t pos = fdp.ConsumeIntegralInRange<size_t>(0, test_str.size());
197
1.03k
                    char ws = fdp.PickValueInArray({' ', '\t', '\n', '\r'});
198
1.03k
                    test_str.insert(pos, 1, ws);
199
1.03k
                }
200
                
201
                // Try decoding with all encoders
202
309
                try { decodeBase64(test_str, decoded_output); } catch (...) {}
203
309
                try { decodeBase32Hex(test_str, decoded_output); } catch (...) {}
204
309
                try { decodeHex(test_str, decoded_output); } catch (...) {}
205
309
            } catch (const isc::Exception&) {
206
                // Expected for whitespace handling
207
0
            }
208
309
            break;
209
309
        }
210
1.34k
    }
211
    
212
1.34k
    return 0;
213
1.34k
}