Coverage Report

Created: 2025-10-10 06:06

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.55k
static void fuzz_tokens(FuzzedDataProvider& fdp) {
31
  // Prepare random string for string comparison
32
1.55k
  std::string payload1 = fdp.ConsumeRandomLengthString(1024);
33
1.55k
  std::string payload2 = fdp.ConsumeRandomLengthString(1024);
34
1.55k
  std::string payload3 = fdp.ConsumeRandomLengthString(1024);
35
1.55k
  const char *payload_str1 = payload1.c_str();
36
1.55k
  const char *payload_str2 = payload2.c_str();
37
1.55k
  const char *payload_str3 = payload3.c_str();
38
1.55k
  size_t payload_size1 = payload1.size();
39
1.55k
  size_t payload_size2 = payload2.size();
40
1.55k
  size_t payload_size3 = payload3.size();
41
42
  // Fuzz mhd_str_equal_caseless
43
1.55k
  mhd_str_equal_caseless(payload_str1, payload_str2);
44
45
  // Fuzz mhd_str_equal_caseless_n
46
1.55k
  mhd_str_equal_caseless_n(payload_str1, payload_str2, fdp.ConsumeIntegral<size_t>());
47
48
  // Fuzz mhd_str_equal_caseless_bin_n
49
1.55k
  const size_t min_len = std::min(payload_size1, payload_size2);
50
1.55k
  if (min_len) {
51
396
    mhd_str_equal_caseless_bin_n(payload_str1, payload_str2, min_len);
52
396
  }
53
54
  // Fuzz mhd_str_has_token_caseless
55
1.55k
  mhd_str_has_token_caseless(payload_str1, payload_str2, payload_size1);
56
1.55k
  mhd_str_has_token_caseless(payload_str1, payload_str2, payload_size2);
57
58
  // Fuzz mhd_str_remove_token_caseless
59
1.55k
  ssize_t out_sz = (ssize_t)fdp.ConsumeIntegralInRange<int>(1, 1024);
60
1.55k
  char *out_buf = (char*) malloc((size_t)out_sz);
61
1.55k
  mhd_str_remove_token_caseless(payload_str1, payload_size1, payload_str2, payload_size2,
62
1.55k
                                out_buf, &out_sz);
63
1.55k
  free(out_buf);
64
65
  // Fuzz mhd_str_starts_with_token_opt_param
66
1.55k
  struct MHD_String mhd_str1 {
67
1.55k
    payload_size1, payload_str1
68
1.55k
  };
69
1.55k
  struct MHD_String mhd_str2 {
70
1.55k
    payload_size2, payload_str2
71
1.55k
  };
72
1.55k
  mhd_str_starts_with_token_opt_param(&mhd_str1, &mhd_str2);
73
74
  // Fuzz mhd_str_starts_with_token_req_param
75
1.55k
  bool needs_uni = fdp.ConsumeBool();
76
1.55k
  struct MHD_String mhd_str3 {
77
1.55k
    payload_size3, payload_str3
78
1.55k
  };
79
1.55k
  struct mhd_BufferConst str3_buf { 0, nullptr };
80
1.55k
  mhd_str_starts_with_token_req_param(&mhd_str1, &mhd_str2, &mhd_str3, &str3_buf, &needs_uni);
81
1.55k
}
82
83
1.52k
static void fuzz_conversion(FuzzedDataProvider& fdp) {
84
  // Prepare random string for string/int conversion
85
1.52k
  std::string payload = fdp.ConsumeRandomLengthString(1024);
86
1.52k
  const char *payload_str = payload.c_str();
87
1.52k
  size_t payload_size = payload.size();
88
89
1.52k
  uint_fast32_t u32 = 0;
90
1.52k
  uint_fast64_t u64 = 0;
91
1.52k
  char small[4], big[128];
92
1.52k
  size_t max_len = fdp.ConsumeIntegralInRange<size_t>(0, payload_size);
93
94
  // Fuzz conversion between string and uint64 with random payload
95
1.52k
  mhd_str_to_uint64(payload_str, &u64);
96
1.52k
  mhd_str_to_uint64_n(payload_str, max_len, &u64);
97
1.52k
  mhd_strx_to_uint64(payload_str, &u64);
98
1.52k
  mhd_strx_to_uint64_n(payload_str, max_len, &u64);
99
1.52k
  mhd_uint64_to_str((uint_fast64_t)fdp.ConsumeIntegral<uint64_t>(), small, sizeof(small));
100
1.52k
  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.52k
  mhd_strx_to_uint32(payload_str, &u32);
104
1.52k
  mhd_strx_to_uint32_n(payload_str, max_len, &u32);
105
1.52k
  mhd_uint32_to_strx((uint_fast32_t)fdp.ConsumeIntegral<uint32_t>(), small, sizeof(small));
106
1.52k
  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.52k
  mhd_uint16_to_str((uint_least16_t)fdp.ConsumeIntegralInRange<unsigned>(0, 65535), small, sizeof(small));
110
1.52k
  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.52k
  uint8_t min_digits = fdp.ConsumeIntegralInRange<uint8_t>(0, 5);
114
1.52k
  mhd_uint8_to_str_pad((uint8_t)fdp.ConsumeIntegral<uint8_t>(), min_digits, small, sizeof(small));
115
1.52k
  mhd_uint8_to_str_pad((uint8_t)fdp.ConsumeIntegral<uint8_t>(), min_digits, big, sizeof(big));
116
1.52k
}
117
118
381
static void fuzz_decode(FuzzedDataProvider& fdp) {
119
  // Prepare random data for string decode
120
381
  bool ignored = false;
121
381
  std::string payload = fdp.ConsumeRandomLengthString(1024);
122
381
  char *payload_str = payload.data();
123
381
  size_t payload_size = payload.size();
124
125
  // Fuzz decode functions with random payload
126
381
  char *out1 = (char*) malloc(payload_size);
127
381
  char *out2 = (char*) malloc(payload_size);
128
381
  if (out1) {
129
381
    mhd_str_pct_decode_strict_n(payload_str, payload_size, out1, payload_size);
130
381
  }
131
381
  if (out2) {
132
381
    mhd_str_pct_decode_lenient_n(payload_str, payload_size, out2, payload_size, &ignored);
133
381
  }
134
135
  // Fuzz decode in place functions with random payload
136
381
  mhd_str_pct_decode_in_place_strict(payload_str);
137
381
  mhd_str_pct_decode_in_place_lenient(payload_str, &ignored);
138
139
381
  free(out1);
140
381
  free(out2);
141
381
}
142
143
508
static void fuzz_quoted(FuzzedDataProvider& fdp) {
144
  // Prepare random data for quote and equality check
145
508
  std::string payload1 = fdp.ConsumeRandomLengthString(1024);
146
508
  std::string payload2 = fdp.ConsumeRandomLengthString(1024);
147
508
  const char *payload_str1 = payload1.c_str();
148
508
  const char *payload_str2 = payload2.c_str();
149
508
  size_t payload_size1 = payload1.size();
150
508
  size_t payload_size2 = payload2.size();
151
152
  // Fuzz mhd_str_equal_quoted_bin_n with random string payload as binary
153
508
  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
508
  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
508
  size_t max_out = payload_size1 * 2;
160
508
  char *out = (char*) malloc(max_out);
161
508
  if (out) {
162
508
    mhd_str_quote(payload_str1, payload_size1, out, max_out);
163
508
    mhd_str_unquote(payload_str1, payload_size1, out);
164
508
  }
165
508
  free(out);
166
167
508
  max_out = payload_size2 * 2;
168
508
  out = (char*) malloc(max_out);
169
508
  if (out) {
170
508
    mhd_str_quote(payload_str2, payload_size2, out, max_out);
171
508
    mhd_str_unquote(payload_str2, payload_size2, out);
172
508
  }
173
508
  free(out);
174
508
}
175
176
327
static void fuzz_base64(FuzzedDataProvider& fdp) {
177
  // Prepare random data for base64 conversion
178
327
  std::string payload = fdp.ConsumeRandomLengthString(1024);
179
327
  char *payload_str = payload.data();
180
327
  size_t payload_size = payload.size();
181
182
  // Prepare a valid base64 string from random payload
183
327
  static const char valid_chars[] =
184
327
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
185
85.8k
  for (size_t i = 0; i < payload_size; i++) {
186
85.4k
    payload_str[i] = valid_chars[((uint8_t)i) % 64];
187
85.4k
  }
188
189
  // Fuzz mhd_base64_to_bin_n with the random base64 string
190
327
  size_t max_out = (payload.size() / 4) * 4;
191
327
  uint8_t* out = (uint8_t*) malloc(payload_size);
192
327
  if (out) {
193
327
    mhd_base64_to_bin_n(payload_str, payload_size, out, max_out);
194
327
    free(out);
195
327
  }
196
327
}
197
198
167
static void fuzz_transformation(FuzzedDataProvider& fdp) {
199
  // Fuzz targets in multiple rounds
200
740
  for (int i = 0; i < fdp.ConsumeIntegralInRange<unsigned>(1, 8); i++) {
201
    // Generate random integer
202
573
    int value = fdp.ConsumeIntegral<int>();
203
204
    // Fuzz conversion functions
205
573
    MHD_http_method_to_string(static_cast<MHD_HTTP_Method>(value));
206
573
    MHD_predef_header_to_string(static_cast<MHD_PredefinedHeader>(value));
207
573
    MHD_protocol_version_to_string(static_cast<MHD_HTTP_ProtocolVersion>(value));
208
573
  }
209
167
}
210
211
267
static void fuzz_hex_conversion(FuzzedDataProvider& fdp) {
212
  // Prepare random data for hex conversion
213
267
  std::string payload = fdp.ConsumeRandomLengthString(1024);
214
267
  char *payload_str = payload.data();
215
267
  size_t payload_size = payload.size();
216
217
  // Fuzz mhd_hex_to_bin with random payload
218
267
  uint8_t *bin_out = (uint8_t*) malloc(payload_size);
219
267
  if (bin_out) {
220
267
    mhd_hex_to_bin(payload_str, payload_size, bin_out);
221
267
    free(bin_out);
222
267
  }
223
224
  // Fuzz mhd_bin_to_hex with random payload
225
267
  char *hex_out = (char *) malloc(payload_size * 2);
226
267
  if (hex_out) {
227
267
    if (!payload.empty()) {
228
206
      mhd_bin_to_hex(payload_str, payload_size, hex_out);
229
206
    }
230
267
    free(hex_out);
231
267
  }
232
233
267
  char *hexz_out = (char *) malloc(payload_size * 2 + 1);
234
267
  if (hexz_out) {
235
267
    if (!payload.empty()) {
236
206
      mhd_bin_to_hex_z(payload_str, payload_size, hexz_out);
237
206
    }
238
267
    free(hexz_out);
239
267
  }
240
267
}
241
242
2.96k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
243
2.96k
  FuzzedDataProvider fdp(data, size);
244
245
7.80k
  for (int i = 0; i < fdp.ConsumeIntegralInRange<unsigned>(1, 6); i++) {
246
4.83k
    switch (fdp.ConsumeIntegralInRange<int>(0, 7)) {
247
1.55k
      case 0: fuzz_tokens(fdp); break;
248
1.52k
      case 1: fuzz_conversion(fdp); break;
249
381
      case 2: fuzz_decode(fdp); break;
250
508
      case 3: fuzz_quoted(fdp); break;
251
327
      case 4: fuzz_base64(fdp); break;
252
167
      case 5: fuzz_transformation(fdp); break;
253
267
      case 6: fuzz_hex_conversion(fdp); break;
254
4.83k
    }
255
4.83k
  }
256
2.96k
  return 0;
257
2.96k
}