Coverage Report

Created: 2025-07-11 06:21

/src/http_fuzzer.cc
Line
Count
Source (jump to first uncovered line)
1
/* Copyright 2023 Google LLC
2
Licensed under the Apache License, Version 2.0 (the "License");
3
you may not use this file except in compliance with the License.
4
You may obtain a copy of the License at
5
      http://www.apache.org/licenses/LICENSE-2.0
6
Unless required by applicable law or agreed to in writing, software
7
distributed under the License is distributed on an "AS IS" BASIS,
8
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
See the License for the specific language governing permissions and
10
limitations under the License.
11
*/
12
13
#include <stddef.h>
14
#include <stdint.h>
15
#include <stdlib.h>
16
#include <string>
17
#include <sys/socket.h>
18
19
#include <fuzzer/FuzzedDataProvider.h>
20
21
extern "C" {
22
#include "libevent/include/event2/event.h"
23
#include "libevent/include/event2/buffer.h"
24
#include "libevent/include/event2/buffer_compat.h"
25
#include "libevent/include/event2/util.h"
26
#include "libevent/include/event2/event.h"
27
#include "libevent/include/event2/http.h"
28
#include "libevent/include/event2/http_struct.h"
29
#include "libevent/include/event2/buffer.h"
30
#include "libevent/include/event2/bufferevent.h"
31
#include "libevent/http-internal.h"
32
}
33
34
2.70k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
35
2.70k
  if (size < 5) {
36
3
    return 0;
37
3
  }
38
39
  // Decider to determine which request type to parse.
40
2.70k
  uint8_t decider = data[0];
41
2.70k
  data++;
42
2.70k
  size--;
43
2.70k
  int maxHeaderSize = *(int*)data;
44
2.70k
  data += 4;
45
2.70k
  size -= 4;
46
2.70k
  if (maxHeaderSize < 0) {
47
24
    return 0;
48
24
  }
49
50
  // Prepare in case it's used.
51
2.67k
  struct evhttp_connection evcon;
52
2.67k
  evcon.ext_method_cmp = NULL;
53
2.67k
  evcon.max_headers_size = maxHeaderSize % 2048;
54
55
2.67k
  struct evhttp *http_val = NULL;
56
2.67k
  http_val = evhttp_new(NULL);
57
2.67k
  if (http_val == NULL) {
58
0
    return 0;
59
0
  }
60
2.67k
  evcon.http_server = http_val;
61
62
2.67k
  FuzzedDataProvider data_provider(data, size);
63
2.67k
  std::string s1 = data_provider.ConsumeRandomLengthString();
64
65
2.67k
  struct evbuffer *buf = evbuffer_new();
66
2.67k
  evbuffer_add(buf, s1.c_str(), s1.size());
67
68
2.67k
  struct evhttp_request *req = evhttp_request_new(NULL, NULL);
69
70
  // Use either the defailt request type or EVHTTP_REQUEST
71
2.67k
  if (decider % 2 == 1) {
72
1.97k
    req->kind=EVHTTP_REQUEST;
73
1.97k
    req->evcon = &evcon;
74
1.97k
  }
75
76
2.67k
  enum message_read_status data_read;
77
78
2.67k
  data_read = evhttp_parse_firstline_(req, buf);
79
2.67k
  if (data_read != ALL_DATA_READ) {
80
2.58k
    data_read = evhttp_parse_headers_(req, buf);
81
2.58k
    if (data_read != ALL_DATA_READ) {
82
2.53k
      data_read = evhttp_parse_headers_(req, buf);
83
2.53k
      if (data_read != ALL_DATA_READ) {
84
2.50k
        evhttp_request_get_input_headers(req);
85
2.50k
      }
86
2.53k
    }
87
2.58k
  }
88
2.67k
  evhttp_request_get_host(req);
89
90
2.67k
  char *encoded = evhttp_encode_uri(s1.c_str());
91
2.67k
  if (encoded != NULL) {
92
2.67k
    free(encoded);
93
2.67k
  }
94
95
  // Minor utils function
96
2.67k
  char *tmp_escaped = evhttp_htmlescape(s1.c_str());
97
2.67k
  if (tmp_escaped != NULL) {
98
2.67k
    free(tmp_escaped);
99
2.67k
  }
100
101
  // URI utils
102
2.67k
  struct evhttp_uri *uri;
103
2.67k
  uri = evhttp_uri_parse(s1.c_str());
104
2.67k
  if (uri != NULL) {
105
824
    char uri_buf[256];
106
824
    evhttp_uri_join(uri, uri_buf, 256);
107
824
    evhttp_uri_free(uri);
108
824
  }
109
110
  // Cleanup
111
2.67k
  evhttp_request_free(req);
112
2.67k
  evbuffer_free(buf);
113
2.67k
  evhttp_free(http_val);
114
2.67k
  return 0;
115
2.67k
}