Coverage Report

Created: 2025-07-15 06:37

/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
3.16k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
35
3.16k
  if (size < 5) {
36
4
    return 0;
37
4
  }
38
39
  // Decider to determine which request type to parse.
40
3.15k
  uint8_t decider = data[0];
41
3.15k
  data++;
42
3.15k
  size--;
43
3.15k
  int maxHeaderSize = *(int*)data;
44
3.15k
  data += 4;
45
3.15k
  size -= 4;
46
3.15k
  if (maxHeaderSize < 0) {
47
34
    return 0;
48
34
  }
49
50
  // Prepare in case it's used.
51
3.12k
  struct evhttp_connection evcon;
52
3.12k
  evcon.ext_method_cmp = NULL;
53
3.12k
  evcon.max_headers_size = maxHeaderSize % 2048;
54
55
3.12k
  struct evhttp *http_val = NULL;
56
3.12k
  http_val = evhttp_new(NULL);
57
3.12k
  if (http_val == NULL) {
58
0
    return 0;
59
0
  }
60
3.12k
  evcon.http_server = http_val;
61
62
3.12k
  FuzzedDataProvider data_provider(data, size);
63
3.12k
  std::string s1 = data_provider.ConsumeRandomLengthString();
64
65
3.12k
  struct evbuffer *buf = evbuffer_new();
66
3.12k
  evbuffer_add(buf, s1.c_str(), s1.size());
67
68
3.12k
  struct evhttp_request *req = evhttp_request_new(NULL, NULL);
69
70
  // Use either the defailt request type or EVHTTP_REQUEST
71
3.12k
  if (decider % 2 == 1) {
72
2.33k
    req->kind=EVHTTP_REQUEST;
73
2.33k
    req->evcon = &evcon;
74
2.33k
  }
75
76
3.12k
  enum message_read_status data_read;
77
78
3.12k
  data_read = evhttp_parse_firstline_(req, buf);
79
3.12k
  if (data_read != ALL_DATA_READ) {
80
3.01k
    data_read = evhttp_parse_headers_(req, buf);
81
3.01k
    if (data_read != ALL_DATA_READ) {
82
2.96k
      data_read = evhttp_parse_headers_(req, buf);
83
2.96k
      if (data_read != ALL_DATA_READ) {
84
2.93k
        evhttp_request_get_input_headers(req);
85
2.93k
      }
86
2.96k
    }
87
3.01k
  }
88
3.12k
  evhttp_request_get_host(req);
89
90
3.12k
  char *encoded = evhttp_encode_uri(s1.c_str());
91
3.12k
  if (encoded != NULL) {
92
3.12k
    free(encoded);
93
3.12k
  }
94
95
  // Minor utils function
96
3.12k
  char *tmp_escaped = evhttp_htmlescape(s1.c_str());
97
3.12k
  if (tmp_escaped != NULL) {
98
3.12k
    free(tmp_escaped);
99
3.12k
  }
100
101
  // URI utils
102
3.12k
  struct evhttp_uri *uri;
103
3.12k
  uri = evhttp_uri_parse(s1.c_str());
104
3.12k
  if (uri != NULL) {
105
947
    char uri_buf[256];
106
947
    evhttp_uri_join(uri, uri_buf, 256);
107
947
    evhttp_uri_free(uri);
108
947
  }
109
110
  // Cleanup
111
3.12k
  evhttp_request_free(req);
112
3.12k
  evbuffer_free(buf);
113
3.12k
  evhttp_free(http_val);
114
3.12k
  return 0;
115
3.12k
}