Coverage Report

Created: 2025-10-27 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fuzz_str.cpp
Line
Count
Source
1
// Copyright 2025 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
//
15
////////////////////////////////////////////////////////////////////////////////
16
#include <cstring>
17
#include <stddef.h>
18
#include <stdint.h>
19
#include <string.h>
20
#include <stdlib.h>
21
#include <algorithm>
22
#include <vector>
23
24
#include <fuzzer/FuzzedDataProvider.h>
25
extern "C" {
26
  #include "mhd_str.h"
27
  #include "microhttpd2.h"
28
}
29
30
1.65k
static void fuzz_tokens(FuzzedDataProvider& fdp) {
31
  // Prepare random string for string comparison
32
1.65k
  std::string payload1 = fdp.ConsumeRandomLengthString(1024);
33
1.65k
  std::string payload2 = fdp.ConsumeRandomLengthString(1024);
34
1.65k
  std::string payload3 = fdp.ConsumeRandomLengthString(1024);
35
1.65k
  const char *payload_str1 = payload1.c_str();
36
1.65k
  const char *payload_str2 = payload2.c_str();
37
1.65k
  const char *payload_str3 = payload3.c_str();
38
1.65k
  size_t payload_size1 = payload1.size();
39
1.65k
  size_t payload_size2 = payload2.size();
40
1.65k
  size_t payload_size3 = payload3.size();
41
42
  // Fuzz mhd_str_equal_caseless
43
1.65k
  mhd_str_equal_caseless(payload_str1, payload_str2);
44
45
  // Fuzz mhd_str_equal_caseless_n
46
1.65k
  mhd_str_equal_caseless_n(payload_str1, payload_str2, fdp.ConsumeIntegral<size_t>());
47
48
  // Fuzz mhd_str_equal_caseless_bin_n
49
1.65k
  const size_t min_len = std::min(payload_size1, payload_size2);
50
1.65k
  if (min_len) {
51
420
    mhd_str_equal_caseless_bin_n(payload_str1, payload_str2, min_len);
52
420
  }
53
54
  // Fuzz mhd_str_has_token_caseless
55
1.65k
  mhd_str_has_token_caseless(payload_str1, payload_str2, payload_size1);
56
1.65k
  mhd_str_has_token_caseless(payload_str1, payload_str2, payload_size2);
57
58
  // Fuzz mhd_str_remove_token_caseless
59
1.65k
  ssize_t out_sz = (ssize_t)fdp.ConsumeIntegralInRange<int>(1, 1024);
60
1.65k
  char *out_buf = (char*) malloc((size_t)out_sz);
61
1.65k
  mhd_str_remove_token_caseless(payload_str1, payload_size1, payload_str2, payload_size2,
62
1.65k
                                out_buf, &out_sz);
63
1.65k
  free(out_buf);
64
65
  // Fuzz mhd_str_starts_with_token_opt_param
66
1.65k
  struct MHD_String mhd_str1 {
67
1.65k
    payload_size1, payload_str1
68
1.65k
  };
69
1.65k
  struct MHD_String mhd_str2 {
70
1.65k
    payload_size2, payload_str2
71
1.65k
  };
72
1.65k
  mhd_str_starts_with_token_opt_param(&mhd_str1, &mhd_str2);
73
74
  // Fuzz mhd_str_starts_with_token_req_param
75
1.65k
  bool needs_uni = fdp.ConsumeBool();
76
1.65k
  struct MHD_String mhd_str3 {
77
1.65k
    payload_size3, payload_str3
78
1.65k
  };
79
1.65k
  struct mhd_BufferConst str3_buf { 0, nullptr };
80
1.65k
  mhd_str_starts_with_token_req_param(&mhd_str1, &mhd_str2, &mhd_str3, &str3_buf, &needs_uni);
81
1.65k
}
82
83
1.61k
static void fuzz_conversion(FuzzedDataProvider& fdp) {
84
  // Prepare random string for string/int conversion
85
1.61k
  std::string payload = fdp.ConsumeRandomLengthString(1024);
86
1.61k
  const char *payload_str = payload.c_str();
87
1.61k
  size_t payload_size = payload.size();
88
89
1.61k
  uint_fast32_t u32 = 0;
90
1.61k
  uint_fast64_t u64 = 0;
91
1.61k
  char small[4], big[128];
92
1.61k
  size_t max_len = fdp.ConsumeIntegralInRange<size_t>(0, payload_size);
93
94
  // Fuzz conversion between string and uint64 with random payload
95
1.61k
  mhd_str_to_uint64(payload_str, &u64);
96
1.61k
  mhd_str_to_uint64_n(payload_str, max_len, &u64);
97
1.61k
  mhd_strx_to_uint64(payload_str, &u64);
98
1.61k
  mhd_strx_to_uint64_n(payload_str, max_len, &u64);
99
1.61k
  mhd_uint64_to_str((uint_fast64_t)fdp.ConsumeIntegral<uint64_t>(), small, sizeof(small));
100
1.61k
  mhd_uint64_to_str((uint_fast64_t)fdp.ConsumeIntegral<uint64_t>(), big, sizeof(big));
101
102
  // Fuzz string to uint32 conversion with random payload string
103
1.61k
  mhd_strx_to_uint32(payload_str, &u32);
104
1.61k
  mhd_strx_to_uint32_n(payload_str, max_len, &u32);
105
1.61k
  mhd_uint32_to_strx((uint_fast32_t)fdp.ConsumeIntegral<uint32_t>(), small, sizeof(small));
106
1.61k
  mhd_uint32_to_strx((uint_fast32_t)fdp.ConsumeIntegral<uint32_t>(), big, sizeof(big));
107
108
  // Fuzz uint16 to string conversion with random payload
109
1.61k
  mhd_uint16_to_str((uint_least16_t)fdp.ConsumeIntegralInRange<unsigned>(0, 65535), small, sizeof(small));
110
1.61k
  mhd_uint16_to_str((uint_least16_t)fdp.ConsumeIntegralInRange<unsigned>(0, 65535), big, sizeof(big));
111
112
  // Fuzz uint8 to string conversion with random payload
113
1.61k
  uint8_t min_digits = fdp.ConsumeIntegralInRange<uint8_t>(0, 5);
114
1.61k
  mhd_uint8_to_str_pad((uint8_t)fdp.ConsumeIntegral<uint8_t>(), min_digits, small, sizeof(small));
115
1.61k
  mhd_uint8_to_str_pad((uint8_t)fdp.ConsumeIntegral<uint8_t>(), min_digits, big, sizeof(big));
116
1.61k
}
117
118
409
static void fuzz_decode(FuzzedDataProvider& fdp) {
119
  // Prepare random data for string decode
120
409
  bool ignored = false;
121
409
  std::string payload = fdp.ConsumeRandomLengthString(1024);
122
409
  char *payload_str = payload.data();
123
409
  size_t payload_size = payload.size();
124
125
  // Fuzz decode functions with random payload
126
409
  char *out1 = (char*) malloc(payload_size);
127
409
  char *out2 = (char*) malloc(payload_size);
128
409
  if (out1) {
129
409
    mhd_str_pct_decode_strict_n(payload_str, payload_size, out1, payload_size);
130
409
  }
131
409
  if (out2) {
132
409
    mhd_str_pct_decode_lenient_n(payload_str, payload_size, out2, payload_size, &ignored);
133
409
  }
134
135
  // Fuzz decode in place functions with random payload
136
409
  mhd_str_pct_decode_in_place_strict(payload_str);
137
409
  mhd_str_pct_decode_in_place_lenient(payload_str, &ignored);
138
139
409
  free(out1);
140
409
  free(out2);
141
409
}
142
143
511
static void fuzz_quoted(FuzzedDataProvider& fdp) {
144
  // Prepare random data for quote and equality check
145
511
  std::string payload1 = fdp.ConsumeRandomLengthString(1024);
146
511
  std::string payload2 = fdp.ConsumeRandomLengthString(1024);
147
511
  const char *payload_str1 = payload1.c_str();
148
511
  const char *payload_str2 = payload2.c_str();
149
511
  size_t payload_size1 = payload1.size();
150
511
  size_t payload_size2 = payload2.size();
151
152
  // Fuzz mhd_str_equal_quoted_bin_n with random string payload as binary
153
511
  mhd_str_equal_quoted_bin_n(payload_str1, payload_size1, payload_str2, payload_size2);
154
155
  // Fuzz mhd_str_equal_caseless_quoted_bin_n with random string payload as binary
156
511
  mhd_str_equal_caseless_quoted_bin_n(payload_str1, payload_size1, payload_str2, payload_size2);
157
158
  // Fuzz mhd_str_quote and mhd_str_unquote with random string payload
159
511
  size_t max_out = payload_size1 * 2;
160
511
  char *out = (char*) malloc(max_out);
161
511
  if (out) {
162
511
    mhd_str_quote(payload_str1, payload_size1, out, max_out);
163
511
    mhd_str_unquote(payload_str1, payload_size1, out);
164
511
  }
165
511
  free(out);
166
167
511
  max_out = payload_size2 * 2;
168
511
  out = (char*) malloc(max_out);
169
511
  if (out) {
170
511
    mhd_str_quote(payload_str2, payload_size2, out, max_out);
171
511
    mhd_str_unquote(payload_str2, payload_size2, out);
172
511
  }
173
511
  free(out);
174
511
}
175
176
365
static void fuzz_base64(FuzzedDataProvider& fdp) {
177
  // Prepare random data for base64 conversion
178
365
  std::string payload = fdp.ConsumeRandomLengthString(1024);
179
365
  char *payload_str = payload.data();
180
365
  size_t payload_size = payload.size();
181
182
  // Prepare a valid base64 string from random payload
183
365
  static const char valid_chars[] =
184
365
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
185
91.4k
  for (size_t i = 0; i < payload_size; i++) {
186
91.0k
    payload_str[i] = valid_chars[((uint8_t)i) % 64];
187
91.0k
  }
188
189
  // Fuzz mhd_base64_to_bin_n with the random base64 string
190
365
  size_t max_out = (payload.size() / 4) * 4;
191
365
  uint8_t* out = (uint8_t*) malloc(payload_size);
192
365
  if (out) {
193
365
    mhd_base64_to_bin_n(payload_str, payload_size, out, max_out);
194
365
    free(out);
195
365
  }
196
365
}
197
198
178
static void fuzz_transformation(FuzzedDataProvider& fdp) {
199
  // Fuzz targets in multiple rounds
200
816
  for (int i = 0; i < fdp.ConsumeIntegralInRange<unsigned>(1, 8); i++) {
201
    // Generate random integer
202
638
    int value = fdp.ConsumeIntegral<int>();
203
204
    // Fuzz conversion functions
205
638
    MHD_http_method_to_string(static_cast<MHD_HTTP_Method>(value));
206
638
    MHD_predef_header_to_string(static_cast<MHD_PredefinedHeader>(value));
207
638
    MHD_protocol_version_to_string(static_cast<MHD_HTTP_ProtocolVersion>(value));
208
638
  }
209
178
}
210
211
269
static void fuzz_hex_conversion(FuzzedDataProvider& fdp) {
212
  // Prepare random data for hex conversion
213
269
  std::string payload = fdp.ConsumeRandomLengthString(1024);
214
269
  char *payload_str = payload.data();
215
269
  size_t payload_size = payload.size();
216
217
  // Fuzz mhd_hex_to_bin with random payload
218
269
  uint8_t *bin_out = (uint8_t*) malloc(payload_size);
219
269
  if (bin_out) {
220
269
    mhd_hex_to_bin(payload_str, payload_size, bin_out);
221
269
    free(bin_out);
222
269
  }
223
224
  // Fuzz mhd_bin_to_hex with random payload
225
269
  char *hex_out = (char *) malloc(payload_size * 2);
226
269
  if (hex_out) {
227
269
    if (!payload.empty()) {
228
201
      mhd_bin_to_hex(payload_str, payload_size, hex_out);
229
201
    }
230
269
    free(hex_out);
231
269
  }
232
233
269
  char *hexz_out = (char *) malloc(payload_size * 2 + 1);
234
269
  if (hexz_out) {
235
269
    if (!payload.empty()) {
236
201
      mhd_bin_to_hex_z(payload_str, payload_size, hexz_out);
237
201
    }
238
269
    free(hexz_out);
239
269
  }
240
269
}
241
242
3.09k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
243
3.09k
  FuzzedDataProvider fdp(data, size);
244
245
8.21k
  for (int i = 0; i < fdp.ConsumeIntegralInRange<unsigned>(1, 6); i++) {
246
5.11k
    switch (fdp.ConsumeIntegralInRange<int>(0, 7)) {
247
1.65k
      case 0: fuzz_tokens(fdp); break;
248
1.61k
      case 1: fuzz_conversion(fdp); break;
249
409
      case 2: fuzz_decode(fdp); break;
250
511
      case 3: fuzz_quoted(fdp); break;
251
365
      case 4: fuzz_base64(fdp); break;
252
178
      case 5: fuzz_transformation(fdp); break;
253
269
      case 6: fuzz_hex_conversion(fdp); break;
254
5.11k
    }
255
5.11k
  }
256
3.09k
  return 0;
257
3.09k
}