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 | } |