Coverage Report

Created: 2025-08-24 06:12

/src/curl_fuzzer/curl_fuzzer_tlv.cc
Line
Count
Source (jump to first uncovered line)
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) 2017, Max Dymond, <cmeister2@gmail.com>, et al.
9
 *
10
 * This software is licensed as described in the file COPYING, which
11
 * you should have received as part of this distribution. The terms
12
 * are also available at https://curl.se/docs/copyright.html.
13
 *
14
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
 * copies of the Software, and permit persons to whom the Software is
16
 * furnished to do so, under the terms of the COPYING file.
17
 *
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
 * KIND, either express or implied.
20
 *
21
 ***************************************************************************/
22
#include <stdlib.h>
23
#include <string.h>
24
#include <curl/curl.h>
25
#include "curl_fuzzer.h"
26
27
/**
28
 * TLV access function - gets the first TLV from a data stream.
29
 */
30
int fuzz_get_first_tlv(FUZZ_DATA *fuzz,
31
                       TLV *tlv)
32
1.56M
{
33
  /* Reset the cursor. */
34
1.56M
  fuzz->state.data_pos = 0;
35
1.56M
  return fuzz_get_tlv_comn(fuzz, tlv);
36
1.56M
}
37
38
/**
39
 * TLV access function - gets the next TLV from a data stream.
40
*/
41
int fuzz_get_next_tlv(FUZZ_DATA *fuzz,
42
                      TLV *tlv)
43
7.16M
{
44
  /* Advance the cursor by the full length of the previous TLV. */
45
7.16M
  fuzz->state.data_pos += sizeof(TLV_RAW) + tlv->length;
46
47
  /* Work out if there's a TLV's worth of data to read */
48
7.16M
  if(fuzz->state.data_pos + sizeof(TLV_RAW) > fuzz->state.data_len) {
49
    /* No more TLVs to parse */
50
1.27M
    return TLV_RC_NO_MORE_TLVS;
51
1.27M
  }
52
53
5.88M
  return fuzz_get_tlv_comn(fuzz, tlv);
54
7.16M
}
55
56
/**
57
 * Common TLV function for accessing TLVs in a data stream.
58
 */
59
int fuzz_get_tlv_comn(FUZZ_DATA *fuzz,
60
                      TLV *tlv)
61
7.44M
{
62
7.44M
  int rc = 0;
63
7.44M
  size_t data_offset;
64
7.44M
  TLV_RAW *raw;
65
66
  /* Start by casting the data stream to a TLV. */
67
7.44M
  raw = (TLV_RAW *)&fuzz->state.data[fuzz->state.data_pos];
68
7.44M
  data_offset = fuzz->state.data_pos + sizeof(TLV_RAW);
69
70
  /* Set the TLV values. */
71
7.44M
  tlv->type = to_u16(raw->raw_type);
72
7.44M
  tlv->length = to_u32(raw->raw_length);
73
7.44M
  tlv->value = &fuzz->state.data[data_offset];
74
75
7.44M
  FV_PRINTF(fuzz, "TLV: type %x length %u\n", tlv->type, tlv->length);
76
77
  /* Use uint64s to verify lengths of TLVs so that overflow problems don't
78
     matter. */
79
7.44M
  uint64_t check_length = data_offset;
80
7.44M
  check_length += tlv->length;
81
82
7.44M
  uint64_t remaining_len = fuzz->state.data_len;
83
7.44M
  FV_PRINTF(fuzz, "Check length of data: %" PRIu64 " \n", check_length);
84
7.44M
  FV_PRINTF(fuzz, "Remaining length of data: %" PRIu64 " \n", remaining_len);
85
86
  /* Sanity check that the TLV length is ok. */
87
7.44M
  if(check_length > remaining_len) {
88
170k
    FV_PRINTF(fuzz, "Returning TLV_RC_SIZE_ERROR\n");
89
170k
    rc = TLV_RC_SIZE_ERROR;
90
170k
  }
91
92
7.44M
  return rc;
93
7.44M
}
94
95
/**
96
 * Do different actions on the CURL handle for different received TLVs.
97
 */
98
int fuzz_parse_tlv(FUZZ_DATA *fuzz, TLV *tlv)
99
6.06M
{
100
6.06M
  int rc;
101
6.06M
  char *tmp = NULL;
102
6.06M
  uint32_t tmp_u32;
103
6.06M
  curl_slist *new_list;
104
105
6.06M
  switch(tlv->type) {
106
    /* The pointers in response TLVs will always be valid as long as the fuzz
107
       data is in scope, which is the entirety of this file. */
108
33.4k
    FRESPONSETLV(&fuzz->sockman[0], TLV_TYPE_RESPONSE0, 0);
109
37.8k
    FRESPONSETLV(&fuzz->sockman[0], TLV_TYPE_RESPONSE1, 1);
110
18.8k
    FRESPONSETLV(&fuzz->sockman[0], TLV_TYPE_RESPONSE2, 2);
111
32.3k
    FRESPONSETLV(&fuzz->sockman[0], TLV_TYPE_RESPONSE3, 3);
112
9.64k
    FRESPONSETLV(&fuzz->sockman[0], TLV_TYPE_RESPONSE4, 4);
113
21.1k
    FRESPONSETLV(&fuzz->sockman[0], TLV_TYPE_RESPONSE5, 5);
114
7.95k
    FRESPONSETLV(&fuzz->sockman[0], TLV_TYPE_RESPONSE6, 6);
115
11.0k
    FRESPONSETLV(&fuzz->sockman[0], TLV_TYPE_RESPONSE7, 7);
116
3.48k
    FRESPONSETLV(&fuzz->sockman[0], TLV_TYPE_RESPONSE8, 8);
117
22.0k
    FRESPONSETLV(&fuzz->sockman[0], TLV_TYPE_RESPONSE9, 9);
118
3.33k
    FRESPONSETLV(&fuzz->sockman[0], TLV_TYPE_RESPONSE10, 10);
119
120
4.05k
    FRESPONSETLV(&fuzz->sockman[1], TLV_TYPE_SECOND_RESPONSE0, 0);
121
4.26k
    FRESPONSETLV(&fuzz->sockman[1], TLV_TYPE_SECOND_RESPONSE1, 1);
122
123
2.10k
    case TLV_TYPE_UPLOAD1:
124
      /* The pointers in the TLV will always be valid as long as the fuzz data
125
         is in scope, which is the entirety of this file. */
126
127
2.10k
      FCHECK_OPTION_UNSET(fuzz, CURLOPT_UPLOAD);
128
129
2.09k
      fuzz->upload1_data = tlv->value;
130
2.09k
      fuzz->upload1_data_len = tlv->length;
131
132
2.09k
      FSET_OPTION(fuzz, CURLOPT_UPLOAD, 1L);
133
2.09k
      FSET_OPTION(fuzz,
134
2.09k
                  CURLOPT_INFILESIZE_LARGE,
135
2.09k
                  (curl_off_t)fuzz->upload1_data_len);
136
2.09k
      break;
137
138
327k
    case TLV_TYPE_HEADER:
139
      /* Limit the number of headers that can be added to a message to prevent
140
         timeouts. */
141
327k
      if(fuzz->header_list_count >= TLV_MAX_NUM_CURLOPT_HEADER) {
142
15
        rc = 255;
143
15
        goto EXIT_LABEL;
144
15
      }
145
146
327k
      tmp = fuzz_tlv_to_string(tlv);
147
327k
      if (tmp == NULL) {
148
        // keep on despite allocation failure
149
0
        break;
150
0
      }
151
327k
      new_list = curl_slist_append(fuzz->header_list, tmp);
152
327k
      if (new_list == NULL) {
153
0
        break;
154
0
      }
155
327k
      fuzz->header_list = new_list;
156
327k
      fuzz->header_list_count++;
157
327k
      break;
158
159
30.0k
    case TLV_TYPE_MAIL_RECIPIENT:
160
      /* Limit the number of headers that can be added to a message to prevent
161
         timeouts. */
162
30.0k
      if(fuzz->header_list_count >= TLV_MAX_NUM_CURLOPT_HEADER) {
163
14
        rc = 255;
164
14
        goto EXIT_LABEL;
165
14
      }
166
30.0k
      tmp = fuzz_tlv_to_string(tlv);
167
30.0k
      if (tmp == NULL) {
168
        // keep on despite allocation failure
169
0
        break;
170
0
      }
171
30.0k
      new_list = curl_slist_append(fuzz->mail_recipients_list, tmp);
172
30.0k
      if (new_list != NULL) {
173
30.0k
        fuzz->mail_recipients_list = new_list;
174
30.0k
        fuzz->header_list_count++;
175
30.0k
      }
176
30.0k
      break;
177
178
5.09M
    case TLV_TYPE_MIME_PART:
179
5.09M
      if(fuzz->mime == NULL) {
180
6.40k
        fuzz->mime = curl_mime_init(fuzz->easy);
181
6.40k
      }
182
183
5.09M
      fuzz->part = curl_mime_addpart(fuzz->mime);
184
185
      /* This TLV may have sub TLVs. */
186
5.09M
      fuzz_add_mime_part(tlv, fuzz->part);
187
188
5.09M
      break;
189
190
1.73k
    case TLV_TYPE_POSTFIELDS:
191
1.73k
      FCHECK_OPTION_UNSET(fuzz, CURLOPT_POSTFIELDS);
192
1.72k
      fuzz->postfields = fuzz_tlv_to_string(tlv);
193
1.72k
      FSET_OPTION(fuzz, CURLOPT_POSTFIELDS, fuzz->postfields);
194
1.72k
      break;
195
196
1.25k
    case TLV_TYPE_HTTPPOSTBODY:
197
1.25k
      FCHECK_OPTION_UNSET(fuzz, CURLOPT_HTTPPOST);
198
1.23k
      fuzz_setup_http_post(fuzz, tlv);
199
1.23k
      FSET_OPTION(fuzz, CURLOPT_HTTPPOST, fuzz->httppost);
200
1.23k
      break;
201
202
    /* Define a set of u32 options. */
203
20.2k
    FU32TLV(fuzz, TLV_TYPE_HTTPAUTH, CURLOPT_HTTPAUTH);
204
1.48k
    FU32TLV(fuzz, TLV_TYPE_OPTHEADER, CURLOPT_HEADER);
205
2.47k
    FU32TLV(fuzz, TLV_TYPE_NOBODY, CURLOPT_NOBODY);
206
7.85k
    FU32TLV(fuzz, TLV_TYPE_FOLLOWLOCATION, CURLOPT_FOLLOWLOCATION);
207
2.21k
    FU32TLV(fuzz, TLV_TYPE_WILDCARDMATCH, CURLOPT_WILDCARDMATCH);
208
8.32k
    FU32TLV(fuzz, TLV_TYPE_RTSP_REQUEST, CURLOPT_RTSP_REQUEST);
209
413
    FU32TLV(fuzz, TLV_TYPE_RTSP_CLIENT_CSEQ, CURLOPT_RTSP_CLIENT_CSEQ);
210
56.7k
    FU32TLV(fuzz, TLV_TYPE_HTTP_VERSION, CURLOPT_HTTP_VERSION);
211
3.04k
    FU32TLV(fuzz, TLV_TYPE_NETRC, CURLOPT_NETRC);
212
375
    FU32TLV(fuzz, TLV_TYPE_WS_OPTIONS, CURLOPT_WS_OPTIONS);
213
2.60k
    FU32TLV(fuzz, TLV_TYPE_CONNECT_ONLY, CURLOPT_CONNECT_ONLY);
214
1.67k
    FU32TLV(fuzz, TLV_TYPE_POST, CURLOPT_POST);
215
51.7k
    FU32TLV(fuzz, TLV_TYPE_PROXYTYPE, CURLOPT_PROXYTYPE);
216
2.90k
    FU32TLV(fuzz, TLV_TYPE_PORT, CURLOPT_PORT);
217
4.86k
    FU32TLV(fuzz, TLV_TYPE_LOW_SPEED_LIMIT, CURLOPT_LOW_SPEED_LIMIT);
218
3.32k
    FU32TLV(fuzz, TLV_TYPE_LOW_SPEED_TIME, CURLOPT_LOW_SPEED_TIME);
219
4.10k
    FU32TLV(fuzz, TLV_TYPE_RESUME_FROM, CURLOPT_RESUME_FROM);
220
460
    FU32TLV(fuzz, TLV_TYPE_TIMEVALUE, CURLOPT_TIMEVALUE);
221
13.5k
    FU32TLV(fuzz, TLV_TYPE_NOPROGRESS, CURLOPT_NOPROGRESS);
222
896
    FU32TLV(fuzz, TLV_TYPE_FAILONERROR, CURLOPT_FAILONERROR);
223
311
    FU32TLV(fuzz, TLV_TYPE_DIRLISTONLY, CURLOPT_DIRLISTONLY);
224
213
    FU32TLV(fuzz, TLV_TYPE_APPEND, CURLOPT_APPEND);
225
4.21k
    FU32TLV(fuzz, TLV_TYPE_TRANSFERTEXT, CURLOPT_TRANSFERTEXT);
226
822
    FU32TLV(fuzz, TLV_TYPE_AUTOREFERER, CURLOPT_AUTOREFERER);
227
2.36k
    FU32TLV(fuzz, TLV_TYPE_PROXYPORT, CURLOPT_PROXYPORT);
228
    // too easy for API misuse FU32TLV(fuzz, TLV_TYPE_POSTFIELDSIZE, CURLOPT_POSTFIELDSIZE);
229
350
    FU32TLV(fuzz, TLV_TYPE_HTTPPROXYTUNNEL, CURLOPT_HTTPPROXYTUNNEL);
230
487
    FU32TLV(fuzz, TLV_TYPE_SSL_VERIFYPEER, CURLOPT_SSL_VERIFYPEER);
231
3.07k
    FU32TLV(fuzz, TLV_TYPE_MAXREDIRS, CURLOPT_MAXREDIRS);
232
730
    FU32TLV(fuzz, TLV_TYPE_FILETIME, CURLOPT_FILETIME);
233
2.39k
    FU32TLV(fuzz, TLV_TYPE_MAXCONNECTS, CURLOPT_MAXCONNECTS);
234
456
    FU32TLV(fuzz, TLV_TYPE_FRESH_CONNECT, CURLOPT_FRESH_CONNECT);
235
328
    FU32TLV(fuzz, TLV_TYPE_FORBID_REUSE, CURLOPT_FORBID_REUSE);
236
5.93k
    FU32TLV(fuzz, TLV_TYPE_CONNECTTIMEOUT, CURLOPT_CONNECTTIMEOUT);
237
273
    FU32TLV(fuzz, TLV_TYPE_HTTPGET, CURLOPT_HTTPGET);
238
443
    FU32TLV(fuzz, TLV_TYPE_SSL_VERIFYHOST, CURLOPT_SSL_VERIFYHOST);
239
195
    FU32TLV(fuzz, TLV_TYPE_FTP_USE_EPSV, CURLOPT_FTP_USE_EPSV);
240
294
    FU32TLV(fuzz, TLV_TYPE_SSLENGINE_DEFAULT, CURLOPT_SSLENGINE_DEFAULT);
241
5.10k
    FU32TLV(fuzz, TLV_TYPE_DNS_CACHE_TIMEOUT, CURLOPT_DNS_CACHE_TIMEOUT);
242
275
    FU32TLV(fuzz, TLV_TYPE_COOKIESESSION, CURLOPT_COOKIESESSION);
243
6.28k
    FU32TLV(fuzz, TLV_TYPE_BUFFERSIZE, CURLOPT_BUFFERSIZE);
244
779
    FU32TLV(fuzz, TLV_TYPE_NOSIGNAL, CURLOPT_NOSIGNAL);
245
560
    FU32TLV(fuzz, TLV_TYPE_UNRESTRICTED_AUTH, CURLOPT_UNRESTRICTED_AUTH);
246
209
    FU32TLV(fuzz, TLV_TYPE_FTP_USE_EPRT, CURLOPT_FTP_USE_EPRT);
247
1.92k
    FU32TLV(fuzz, TLV_TYPE_FTP_CREATE_MISSING_DIRS, CURLOPT_FTP_CREATE_MISSING_DIRS);
248
2.78k
    FU32TLV(fuzz, TLV_TYPE_MAXFILESIZE, CURLOPT_MAXFILESIZE);
249
371
    FU32TLV(fuzz, TLV_TYPE_TCP_NODELAY, CURLOPT_TCP_NODELAY);
250
398
    FU32TLV(fuzz, TLV_TYPE_IGNORE_CONTENT_LENGTH, CURLOPT_IGNORE_CONTENT_LENGTH);
251
260
    FU32TLV(fuzz, TLV_TYPE_FTP_SKIP_PASV_IP, CURLOPT_FTP_SKIP_PASV_IP);
252
3.59k
    FU32TLV(fuzz, TLV_TYPE_LOCALPORT, CURLOPT_LOCALPORT);
253
2.20k
    FU32TLV(fuzz, TLV_TYPE_LOCALPORTRANGE, CURLOPT_LOCALPORTRANGE);
254
259
    FU32TLV(fuzz, TLV_TYPE_SSL_SESSIONID_CACHE, CURLOPT_SSL_SESSIONID_CACHE);
255
980
    FU32TLV(fuzz, TLV_TYPE_FTP_SSL_CCC, CURLOPT_FTP_SSL_CCC);
256
6.51k
    FU32TLV(fuzz, TLV_TYPE_CONNECTTIMEOUT_MS, CURLOPT_CONNECTTIMEOUT_MS);
257
711
    FU32TLV(fuzz, TLV_TYPE_HTTP_TRANSFER_DECODING, CURLOPT_HTTP_TRANSFER_DECODING);
258
321
    FU32TLV(fuzz, TLV_TYPE_HTTP_CONTENT_DECODING, CURLOPT_HTTP_CONTENT_DECODING);
259
1.72k
    FU32TLV(fuzz, TLV_TYPE_NEW_FILE_PERMS, CURLOPT_NEW_FILE_PERMS);
260
191
    FU32TLV(fuzz, TLV_TYPE_NEW_DIRECTORY_PERMS, CURLOPT_NEW_DIRECTORY_PERMS);
261
275
    FU32TLV(fuzz, TLV_TYPE_PROXY_TRANSFER_MODE, CURLOPT_PROXY_TRANSFER_MODE);
262
5.23k
    FU32TLV(fuzz, TLV_TYPE_ADDRESS_SCOPE, CURLOPT_ADDRESS_SCOPE);
263
283
    FU32TLV(fuzz, TLV_TYPE_CERTINFO, CURLOPT_CERTINFO);
264
2.73k
    FU32TLV(fuzz, TLV_TYPE_TFTP_BLKSIZE, CURLOPT_TFTP_BLKSIZE);
265
80
    FU32TLV(fuzz, TLV_TYPE_SOCKS5_GSSAPI_NEC, CURLOPT_SOCKS5_GSSAPI_NEC);
266
270
    FU32TLV(fuzz, TLV_TYPE_FTP_USE_PRET, CURLOPT_FTP_USE_PRET);
267
275
    FU32TLV(fuzz, TLV_TYPE_RTSP_SERVER_CSEQ, CURLOPT_RTSP_SERVER_CSEQ);
268
909
    FU32TLV(fuzz, TLV_TYPE_TRANSFER_ENCODING, CURLOPT_TRANSFER_ENCODING);
269
1.73k
    FU32TLV(fuzz, TLV_TYPE_ACCEPTTIMEOUT_MS, CURLOPT_ACCEPTTIMEOUT_MS);
270
1.36k
    FU32TLV(fuzz, TLV_TYPE_TCP_KEEPALIVE, CURLOPT_TCP_KEEPALIVE);
271
3.07k
    FU32TLV(fuzz, TLV_TYPE_TCP_KEEPIDLE, CURLOPT_TCP_KEEPIDLE);
272
2.46k
    FU32TLV(fuzz, TLV_TYPE_TCP_KEEPINTVL, CURLOPT_TCP_KEEPINTVL);
273
582
    FU32TLV(fuzz, TLV_TYPE_SASL_IR, CURLOPT_SASL_IR);
274
461
    FU32TLV(fuzz, TLV_TYPE_SSL_ENABLE_ALPN, CURLOPT_SSL_ENABLE_ALPN);
275
1.43k
    FU32TLV(fuzz, TLV_TYPE_EXPECT_100_TIMEOUT_MS, CURLOPT_EXPECT_100_TIMEOUT_MS);
276
560
    FU32TLV(fuzz, TLV_TYPE_SSL_VERIFYSTATUS, CURLOPT_SSL_VERIFYSTATUS);
277
87
    FU32TLV(fuzz, TLV_TYPE_SSL_FALSESTART, CURLOPT_SSL_FALSESTART);
278
541
    FU32TLV(fuzz, TLV_TYPE_PATH_AS_IS, CURLOPT_PATH_AS_IS);
279
360
    FU32TLV(fuzz, TLV_TYPE_PIPEWAIT, CURLOPT_PIPEWAIT);
280
2.38k
    FU32TLV(fuzz, TLV_TYPE_STREAM_WEIGHT, CURLOPT_STREAM_WEIGHT);
281
471
    FU32TLV(fuzz, TLV_TYPE_TFTP_NO_OPTIONS, CURLOPT_TFTP_NO_OPTIONS);
282
205
    FU32TLV(fuzz, TLV_TYPE_TCP_FASTOPEN, CURLOPT_TCP_FASTOPEN);
283
268
    FU32TLV(fuzz, TLV_TYPE_KEEP_SENDING_ON_ERROR, CURLOPT_KEEP_SENDING_ON_ERROR);
284
1.56k
    FU32TLV(fuzz, TLV_TYPE_PROXY_SSL_VERIFYPEER, CURLOPT_PROXY_SSL_VERIFYPEER);
285
429
    FU32TLV(fuzz, TLV_TYPE_PROXY_SSL_VERIFYHOST, CURLOPT_PROXY_SSL_VERIFYHOST);
286
281
    FU32TLV(fuzz, TLV_TYPE_PROXY_SSL_OPTIONS, CURLOPT_PROXY_SSL_OPTIONS);
287
865
    FU32TLV(fuzz, TLV_TYPE_SUPPRESS_CONNECT_HEADERS, CURLOPT_SUPPRESS_CONNECT_HEADERS);
288
1.35k
    FU32TLV(fuzz, TLV_TYPE_SOCKS5_AUTH, CURLOPT_SOCKS5_AUTH);
289
162
    FU32TLV(fuzz, TLV_TYPE_SSH_COMPRESSION, CURLOPT_SSH_COMPRESSION);
290
361
    FU32TLV(fuzz, TLV_TYPE_HAPPY_EYEBALLS_TIMEOUT_MS, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS);
291
507
    FU32TLV(fuzz, TLV_TYPE_HAPROXYPROTOCOL, CURLOPT_HAPROXYPROTOCOL);
292
1.04k
    FU32TLV(fuzz, TLV_TYPE_DNS_SHUFFLE_ADDRESSES, CURLOPT_DNS_SHUFFLE_ADDRESSES);
293
341
    FU32TLV(fuzz, TLV_TYPE_DISALLOW_USERNAME_IN_URL, CURLOPT_DISALLOW_USERNAME_IN_URL);
294
8.48k
    FU32TLV(fuzz, TLV_TYPE_UPLOAD_BUFFERSIZE, CURLOPT_UPLOAD_BUFFERSIZE);
295
1.40k
    FU32TLV(fuzz, TLV_TYPE_UPKEEP_INTERVAL_MS, CURLOPT_UPKEEP_INTERVAL_MS);
296
464
    FU32TLV(fuzz, TLV_TYPE_HTTP09_ALLOWED, CURLOPT_HTTP09_ALLOWED);
297
726
    FU32TLV(fuzz, TLV_TYPE_ALTSVC_CTRL, CURLOPT_ALTSVC_CTRL);
298
2.37k
    FU32TLV(fuzz, TLV_TYPE_MAXAGE_CONN, CURLOPT_MAXAGE_CONN);
299
252
    FU32TLV(fuzz, TLV_TYPE_MAIL_RCPT_ALLOWFAILS, CURLOPT_MAIL_RCPT_ALLOWFAILS);
300
404
    FU32TLV(fuzz, TLV_TYPE_HSTS_CTRL, CURLOPT_HSTS_CTRL);
301
238
    FU32TLV(fuzz, TLV_TYPE_DOH_SSL_VERIFYPEER, CURLOPT_DOH_SSL_VERIFYPEER);
302
170
    FU32TLV(fuzz, TLV_TYPE_DOH_SSL_VERIFYHOST, CURLOPT_DOH_SSL_VERIFYHOST);
303
370
    FU32TLV(fuzz, TLV_TYPE_DOH_SSL_VERIFYSTATUS, CURLOPT_DOH_SSL_VERIFYSTATUS);
304
2.61k
    FU32TLV(fuzz, TLV_TYPE_MAXLIFETIME_CONN, CURLOPT_MAXLIFETIME_CONN);
305
304
    FU32TLV(fuzz, TLV_TYPE_MIME_OPTIONS, CURLOPT_MIME_OPTIONS);
306
3.15k
    FU32TLV(fuzz, TLV_TYPE_CA_CACHE_TIMEOUT, CURLOPT_CA_CACHE_TIMEOUT);
307
256
    FU32TLV(fuzz, TLV_TYPE_QUICK_EXIT, CURLOPT_QUICK_EXIT);
308
1.35k
    FU32TLV(fuzz, TLV_TYPE_SERVER_RESPONSE_TIMEOUT_MS, CURLOPT_SERVER_RESPONSE_TIMEOUT_MS);
309
2.78k
    FU32TLV(fuzz, TLV_TYPE_TCP_KEEPCNT, CURLOPT_TCP_KEEPCNT);
310
3.01k
    FU32TLV(fuzz, TLV_TYPE_SSLVERSION, CURLOPT_SSLVERSION);
311
4.20k
    FU32TLV(fuzz, TLV_TYPE_TIMECONDITION, CURLOPT_TIMECONDITION);
312
4.17k
    FU32TLV(fuzz, TLV_TYPE_PROXYAUTH, CURLOPT_PROXYAUTH);
313
1.97k
    FU32TLV(fuzz, TLV_TYPE_IPRESOLVE, CURLOPT_IPRESOLVE);
314
2.10k
    FU32TLV(fuzz, TLV_TYPE_USE_SSL, CURLOPT_USE_SSL);
315
1.89k
    FU32TLV(fuzz, TLV_TYPE_FTPSSLAUTH, CURLOPT_FTPSSLAUTH);
316
1.91k
    FU32TLV(fuzz, TLV_TYPE_FTP_FILEMETHOD, CURLOPT_FTP_FILEMETHOD);
317
83
    FU32TLV(fuzz, TLV_TYPE_SSH_AUTH_TYPES, CURLOPT_SSH_AUTH_TYPES);
318
1.65k
    FU32TLV(fuzz, TLV_TYPE_POSTREDIR, CURLOPT_POSTREDIR);
319
88
    FU32TLV(fuzz, TLV_TYPE_GSSAPI_DELEGATION, CURLOPT_GSSAPI_DELEGATION);
320
367
    FU32TLV(fuzz, TLV_TYPE_SSL_OPTIONS, CURLOPT_SSL_OPTIONS);
321
6.47k
    FU32TLV(fuzz, TLV_TYPE_HEADEROPT, CURLOPT_HEADEROPT);
322
1.77k
    FU32TLV(fuzz, TLV_TYPE_PROXY_SSLVERSION, CURLOPT_PROXY_SSLVERSION);
323
4.80k
    FU32TLV(fuzz, TLV_TYPE_RESUME_FROM_LARGE, CURLOPT_RESUME_FROM_LARGE);
324
3.22k
    FU32TLV(fuzz, TLV_TYPE_MAXFILESIZE_LARGE, CURLOPT_MAXFILESIZE_LARGE);
325
    // too easy for API misuse FU32TLV(fuzz, TLV_TYPE_POSTFIELDSIZE_LARGE, CURLOPT_POSTFIELDSIZE_LARGE);
326
6.30k
    FU32TLV(fuzz, TLV_TYPE_MAX_SEND_SPEED_LARGE, CURLOPT_MAX_SEND_SPEED_LARGE);
327
10.8k
    FU32TLV(fuzz, TLV_TYPE_MAX_RECV_SPEED_LARGE, CURLOPT_MAX_RECV_SPEED_LARGE);
328
959
    FU32TLV(fuzz, TLV_TYPE_TIMEVALUE_LARGE, CURLOPT_TIMEVALUE_LARGE);
329
330
    /* Define a set of singleton TLVs - they can only have their value set once
331
       and all follow the same pattern. */
332
261k
    FSINGLETONTLV(fuzz, TLV_TYPE_URL, CURLOPT_URL);
333
10.3k
    FSINGLETONTLV(fuzz, TLV_TYPE_DOH_URL, CURLOPT_DOH_URL);
334
3.15k
    FSINGLETONTLV(fuzz, TLV_TYPE_USERNAME, CURLOPT_USERNAME);
335
3.20k
    FSINGLETONTLV(fuzz, TLV_TYPE_PASSWORD, CURLOPT_PASSWORD);
336
1.67k
    FSINGLETONTLV(fuzz, TLV_TYPE_COOKIE, CURLOPT_COOKIE);
337
4.68k
    FSINGLETONTLV(fuzz, TLV_TYPE_RANGE, CURLOPT_RANGE);
338
2.06k
    FSINGLETONTLV(fuzz, TLV_TYPE_CUSTOMREQUEST, CURLOPT_CUSTOMREQUEST);
339
948
    FSINGLETONTLV(fuzz, TLV_TYPE_MAIL_FROM, CURLOPT_MAIL_FROM);
340
5.08k
    FSINGLETONTLV(fuzz, TLV_TYPE_ACCEPTENCODING, CURLOPT_ACCEPT_ENCODING);
341
820
    FSINGLETONTLV(fuzz, TLV_TYPE_RTSP_SESSION_ID, CURLOPT_RTSP_SESSION_ID);
342
339
    FSINGLETONTLV(fuzz, TLV_TYPE_RTSP_STREAM_URI, CURLOPT_RTSP_STREAM_URI);
343
402
    FSINGLETONTLV(fuzz, TLV_TYPE_RTSP_TRANSPORT, CURLOPT_RTSP_TRANSPORT);
344
274
    FSINGLETONTLV(fuzz, TLV_TYPE_MAIL_AUTH, CURLOPT_MAIL_AUTH);
345
996
    FSINGLETONTLV(fuzz, TLV_TYPE_LOGIN_OPTIONS, CURLOPT_LOGIN_OPTIONS);
346
2.62k
    FSINGLETONTLV(fuzz, TLV_TYPE_XOAUTH2_BEARER, CURLOPT_XOAUTH2_BEARER);
347
3.37k
    FSINGLETONTLV(fuzz, TLV_TYPE_USERPWD, CURLOPT_USERPWD);
348
2.74k
    FSINGLETONTLV(fuzz, TLV_TYPE_USERAGENT, CURLOPT_USERAGENT);
349
122
    FSINGLETONTLV(fuzz, TLV_TYPE_SSH_HOST_PUBLIC_KEY_SHA256, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256);
350
38.0k
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY, CURLOPT_PROXY);
351
5.11k
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXYUSERPWD, CURLOPT_PROXYUSERPWD);
352
452
    FSINGLETONTLV(fuzz, TLV_TYPE_REFERER, CURLOPT_REFERER);
353
844
    FSINGLETONTLV(fuzz, TLV_TYPE_FTPPORT, CURLOPT_FTPPORT);
354
552
    FSINGLETONTLV(fuzz, TLV_TYPE_SSLCERT, CURLOPT_SSLCERT);
355
136
    FSINGLETONTLV(fuzz, TLV_TYPE_KEYPASSWD, CURLOPT_KEYPASSWD);
356
7.02k
    FSINGLETONTLV(fuzz, TLV_TYPE_INTERFACE, CURLOPT_INTERFACE);
357
42
    FSINGLETONTLV(fuzz, TLV_TYPE_KRBLEVEL, CURLOPT_KRBLEVEL);
358
1.83k
    FSINGLETONTLV(fuzz, TLV_TYPE_CAINFO, CURLOPT_CAINFO);
359
17.2k
    FSINGLETONTLV(fuzz, TLV_TYPE_SSL_CIPHER_LIST, CURLOPT_SSL_CIPHER_LIST);
360
378
    FSINGLETONTLV(fuzz, TLV_TYPE_SSLCERTTYPE, CURLOPT_SSLCERTTYPE);
361
92
    FSINGLETONTLV(fuzz, TLV_TYPE_SSLKEY, CURLOPT_SSLKEY);
362
106
    FSINGLETONTLV(fuzz, TLV_TYPE_SSLKEYTYPE, CURLOPT_SSLKEYTYPE);
363
22.3k
    FSINGLETONTLV(fuzz, TLV_TYPE_SSLENGINE, CURLOPT_SSLENGINE);
364
1.36k
    FSINGLETONTLV(fuzz, TLV_TYPE_CAPATH, CURLOPT_CAPATH);
365
136
    FSINGLETONTLV(fuzz, TLV_TYPE_FTP_ACCOUNT, CURLOPT_FTP_ACCOUNT);
366
31.4k
    FSINGLETONTLV(fuzz, TLV_TYPE_COOKIELIST, CURLOPT_COOKIELIST);
367
150
    FSINGLETONTLV(fuzz, TLV_TYPE_FTP_ALTERNATIVE_TO_USER, CURLOPT_FTP_ALTERNATIVE_TO_USER);
368
36
    FSINGLETONTLV(fuzz, TLV_TYPE_SSH_PUBLIC_KEYFILE, CURLOPT_SSH_PUBLIC_KEYFILE);
369
34
    FSINGLETONTLV(fuzz, TLV_TYPE_SSH_PRIVATE_KEYFILE, CURLOPT_SSH_PRIVATE_KEYFILE);
370
36
    FSINGLETONTLV(fuzz, TLV_TYPE_SSH_HOST_PUBLIC_KEY_MD5, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5);
371
236
    FSINGLETONTLV(fuzz, TLV_TYPE_ISSUERCERT, CURLOPT_ISSUERCERT);
372
334
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXYUSERNAME, CURLOPT_PROXYUSERNAME);
373
274
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXYPASSWORD, CURLOPT_PROXYPASSWORD);
374
5.32k
    FSINGLETONTLV(fuzz, TLV_TYPE_NOPROXY, CURLOPT_NOPROXY);
375
38
    FSINGLETONTLV(fuzz, TLV_TYPE_SSH_KNOWNHOSTS, CURLOPT_SSH_KNOWNHOSTS);
376
406
    FSINGLETONTLV(fuzz, TLV_TYPE_TLSAUTH_USERNAME, CURLOPT_TLSAUTH_USERNAME);
377
626
    FSINGLETONTLV(fuzz, TLV_TYPE_TLSAUTH_PASSWORD, CURLOPT_TLSAUTH_PASSWORD);
378
124
    FSINGLETONTLV(fuzz, TLV_TYPE_TLSAUTH_TYPE, CURLOPT_TLSAUTH_TYPE);
379
50
    FSINGLETONTLV(fuzz, TLV_TYPE_DNS_SERVERS, CURLOPT_DNS_SERVERS);
380
40
    FSINGLETONTLV(fuzz, TLV_TYPE_DNS_INTERFACE, CURLOPT_DNS_INTERFACE);
381
48
    FSINGLETONTLV(fuzz, TLV_TYPE_DNS_LOCAL_IP4, CURLOPT_DNS_LOCAL_IP4);
382
38
    FSINGLETONTLV(fuzz, TLV_TYPE_DNS_LOCAL_IP6, CURLOPT_DNS_LOCAL_IP6);
383
462
    FSINGLETONTLV(fuzz, TLV_TYPE_PINNEDPUBLICKEY, CURLOPT_PINNEDPUBLICKEY);
384
1.80k
    FSINGLETONTLV(fuzz, TLV_TYPE_UNIX_SOCKET_PATH, CURLOPT_UNIX_SOCKET_PATH);
385
338
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_SERVICE_NAME, CURLOPT_PROXY_SERVICE_NAME);
386
278
    FSINGLETONTLV(fuzz, TLV_TYPE_SERVICE_NAME, CURLOPT_SERVICE_NAME);
387
2.58k
    FSINGLETONTLV(fuzz, TLV_TYPE_DEFAULT_PROTOCOL, CURLOPT_DEFAULT_PROTOCOL);
388
460
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_CAINFO, CURLOPT_PROXY_CAINFO);
389
882
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_CAPATH, CURLOPT_PROXY_CAPATH);
390
300
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_TLSAUTH_USERNAME, CURLOPT_PROXY_TLSAUTH_USERNAME);
391
218
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_TLSAUTH_PASSWORD, CURLOPT_PROXY_TLSAUTH_PASSWORD);
392
124
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_TLSAUTH_TYPE, CURLOPT_PROXY_TLSAUTH_TYPE);
393
292
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_SSLCERT, CURLOPT_PROXY_SSLCERT);
394
152
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_SSLCERTTYPE, CURLOPT_PROXY_SSLCERTTYPE);
395
130
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_SSLKEY, CURLOPT_PROXY_SSLKEY);
396
126
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_SSLKEYTYPE, CURLOPT_PROXY_SSLKEYTYPE);
397
458
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_KEYPASSWD, CURLOPT_PROXY_KEYPASSWD);
398
9.59k
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_SSL_CIPHER_LIST, CURLOPT_PROXY_SSL_CIPHER_LIST);
399
400
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_CRLFILE, CURLOPT_PROXY_CRLFILE);
400
51.9k
    FSINGLETONTLV(fuzz, TLV_TYPE_PRE_PROXY, CURLOPT_PRE_PROXY);
401
362
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_PINNEDPUBLICKEY, CURLOPT_PROXY_PINNEDPUBLICKEY);
402
1.23k
    FSINGLETONTLV(fuzz, TLV_TYPE_ABSTRACT_UNIX_SOCKET, CURLOPT_ABSTRACT_UNIX_SOCKET);
403
644
    FSINGLETONTLV(fuzz, TLV_TYPE_REQUEST_TARGET, CURLOPT_REQUEST_TARGET);
404
4.11k
    FSINGLETONTLV(fuzz, TLV_TYPE_TLS13_CIPHERS, CURLOPT_TLS13_CIPHERS);
405
2.39k
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_TLS13_CIPHERS, CURLOPT_PROXY_TLS13_CIPHERS);
406
230
    FSINGLETONTLV(fuzz, TLV_TYPE_SASL_AUTHZID, CURLOPT_SASL_AUTHZID);
407
258
    FSINGLETONTLV(fuzz, TLV_TYPE_PROXY_ISSUERCERT, CURLOPT_PROXY_ISSUERCERT);
408
6.31k
    FSINGLETONTLV(fuzz, TLV_TYPE_SSL_EC_CURVES, CURLOPT_SSL_EC_CURVES);
409
15.3k
    FSINGLETONTLV(fuzz, TLV_TYPE_AWS_SIGV4, CURLOPT_AWS_SIGV4);
410
3.30k
    FSINGLETONTLV(fuzz, TLV_TYPE_REDIR_PROTOCOLS_STR, CURLOPT_REDIR_PROTOCOLS_STR);
411
1.17k
    FSINGLETONTLV(fuzz, TLV_TYPE_HAPROXY_CLIENT_IP, CURLOPT_HAPROXY_CLIENT_IP);
412
36
    FSINGLETONTLV(fuzz, TLV_TYPE_ECH, CURLOPT_ECH);
413
603
    default:
414
      /* The fuzzer generates lots of unknown TLVs - we don't want these in the
415
         corpus so we reject any unknown TLVs. */
416
603
      rc = 127;
417
603
      goto EXIT_LABEL;
418
0
      break;
419
6.06M
  }
420
421
6.04M
  rc = 0;
422
423
6.06M
EXIT_LABEL:
424
425
6.06M
  fuzz_free((void **)&tmp);
426
427
6.06M
  return rc;
428
6.04M
}
429
430
/**
431
 * Converts a TLV data and length into an allocated string.
432
 */
433
char *fuzz_tlv_to_string(TLV *tlv)
434
1.73M
{
435
1.73M
  char *tlvstr;
436
437
  /* Allocate enough space, plus a null terminator */
438
1.73M
  tlvstr = (char *)malloc(tlv->length + 1);
439
440
1.73M
  if(tlvstr != NULL) {
441
1.73M
    memcpy(tlvstr, tlv->value, tlv->length);
442
1.73M
    tlvstr[tlv->length] = 0;
443
1.73M
  }
444
445
1.73M
  return tlvstr;
446
1.73M
}
447
448
/* set up for CURLOPT_HTTPPOST, an alternative API to CURLOPT_MIMEPOST */
449
void fuzz_setup_http_post(FUZZ_DATA *fuzz, TLV *tlv)
450
1.23k
{
451
1.23k
  if (fuzz->httppost == NULL) {
452
1.23k
    struct curl_httppost *post = NULL;
453
1.23k
    struct curl_httppost *last = NULL;
454
455
1.23k
    fuzz->post_body = fuzz_tlv_to_string(tlv);
456
1.23k
    if (fuzz->post_body == NULL) {
457
0
      return;
458
0
    }
459
460
    /* This is just one of several possible entrypoints to
461
     * the HTTPPOST API. see https://curl.se/libcurl/c/curl_formadd.html
462
     * for lots of others which could be added here.
463
     */
464
1.23k
    curl_formadd(&post, &last,
465
1.23k
     CURLFORM_COPYNAME, FUZZ_HTTPPOST_NAME,
466
1.23k
     CURLFORM_PTRCONTENTS, fuzz->post_body,
467
1.23k
     CURLFORM_CONTENTLEN, (curl_off_t) strlen(fuzz->post_body),
468
1.23k
     CURLFORM_END);
469
470
1.23k
    fuzz->last_post_part = last;
471
1.23k
    fuzz->httppost = post;
472
1.23k
  }
473
474
1.23k
  return;
475
1.23k
}
476
477
/**
478
 * Extract the values from the TLV.
479
 */
480
int fuzz_add_mime_part(TLV *src_tlv, curl_mimepart *part)
481
5.09M
{
482
5.09M
  FUZZ_DATA part_fuzz;
483
5.09M
  TLV tlv;
484
5.09M
  int rc = 0;
485
5.09M
  int tlv_rc;
486
487
5.09M
  memset(&part_fuzz, 0, sizeof(FUZZ_DATA));
488
489
5.09M
  if(src_tlv->length < sizeof(TLV_RAW)) {
490
    /* Not enough data for a single TLV - don't continue */
491
3.73M
    goto EXIT_LABEL;
492
3.73M
  }
493
494
  /* Set up the state parser */
495
1.36M
  part_fuzz.state.data = src_tlv->value;
496
1.36M
  part_fuzz.state.data_len = src_tlv->length;
497
498
1.36M
  for(tlv_rc = fuzz_get_first_tlv(&part_fuzz, &tlv);
499
2.47M
      tlv_rc == 0;
500
1.36M
      tlv_rc = fuzz_get_next_tlv(&part_fuzz, &tlv)) {
501
502
    /* Have the TLV in hand. Parse the TLV. */
503
1.20M
    rc = fuzz_parse_mime_tlv(part, &tlv);
504
505
1.20M
    if(rc != 0) {
506
      /* Failed to parse the TLV. Can't continue. */
507
90.6k
      goto EXIT_LABEL;
508
90.6k
    }
509
1.20M
  }
510
511
1.27M
  if(tlv_rc != TLV_RC_NO_MORE_TLVS) {
512
    /* A TLV call failed. Can't continue. */
513
168k
    goto EXIT_LABEL;
514
168k
  }
515
516
5.09M
EXIT_LABEL:
517
518
5.09M
  return(rc);
519
1.27M
}
520
521
/**
522
 * Do different actions on the mime part for different received TLVs.
523
 */
524
int fuzz_parse_mime_tlv(curl_mimepart *part, TLV *tlv)
525
1.20M
{
526
1.20M
  int rc;
527
1.20M
  char *tmp;
528
529
1.20M
  switch(tlv->type) {
530
1.09M
    case TLV_TYPE_MIME_PART_NAME:
531
1.09M
      tmp = fuzz_tlv_to_string(tlv);
532
1.09M
      curl_mime_name(part, tmp);
533
1.09M
      fuzz_free((void **)&tmp);
534
1.09M
      break;
535
536
18.7k
    case TLV_TYPE_MIME_PART_DATA:
537
18.7k
      curl_mime_data(part, (const char *)tlv->value, tlv->length);
538
18.7k
      break;
539
540
90.6k
    default:
541
      /* The fuzzer generates lots of unknown TLVs - we don't want these in the
542
         corpus so we reject any unknown TLVs. */
543
90.6k
      rc = 255;
544
90.6k
      goto EXIT_LABEL;
545
0
      break;
546
1.20M
  }
547
548
1.11M
  rc = 0;
549
550
1.20M
EXIT_LABEL:
551
552
1.20M
  return rc;
553
1.11M
}