| 40 | std::string RequestMethodString(HTTPRequest::RequestMethod m); |
| 41 | |
| 42 | FUZZ_TARGET(http_request) |
| 43 | { |
| 44 | FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; |
| 45 | evhttp_request* evreq = evhttp_request_new(nullptr, nullptr); |
| 46 | assert(evreq != nullptr); |
| 47 | evreq->kind = EVHTTP_REQUEST; |
| 48 | evbuffer* evbuf = evbuffer_new(); |
| 49 | assert(evbuf != nullptr); |
| 50 | const std::vector<uint8_t> http_buffer = ConsumeRandomLengthByteVector(fuzzed_data_provider, 4096); |
| 51 | evbuffer_add(evbuf, http_buffer.data(), http_buffer.size()); |
| 52 | // Avoid constructing requests that will be interpreted by libevent as PROXY requests to avoid triggering |
| 53 | // a nullptr dereference. The dereference (req->evcon->http_server) takes place in evhttp_parse_request_line |
| 54 | // and is a consequence of our hacky but necessary use of the internal function evhttp_parse_firstline_ in |
| 55 | // this fuzzing harness. The workaround is not aesthetically pleasing, but it successfully avoids the troublesome |
| 56 | // code path. " http:// HTTP/1.1\n" was a crashing input prior to this workaround. |
| 57 | const std::string http_buffer_str = ToLower({http_buffer.begin(), http_buffer.end()}); |
| 58 | if (http_buffer_str.find(" http://") != std::string::npos || http_buffer_str.find(" https://") != std::string::npos || |
| 59 | evhttp_parse_firstline_(evreq, evbuf) != 1 || evhttp_parse_headers_(evreq, evbuf) != 1) { |
| 60 | evbuffer_free(evbuf); |
| 61 | evhttp_request_free(evreq); |
| 62 | return; |
| 63 | } |
| 64 | |
| 65 | HTTPRequest http_request{evreq, true}; |
| 66 | const HTTPRequest::RequestMethod request_method = http_request.GetRequestMethod(); |
| 67 | (void)RequestMethodString(request_method); |
| 68 | (void)http_request.GetURI(); |
| 69 | (void)http_request.GetHeader("Host"); |
| 70 | const std::string header = fuzzed_data_provider.ConsumeRandomLengthString(16); |
| 71 | (void)http_request.GetHeader(header); |
| 72 | (void)http_request.WriteHeader(header, fuzzed_data_provider.ConsumeRandomLengthString(16)); |
| 73 | (void)http_request.GetHeader(header); |
| 74 | const std::string body = http_request.ReadBody(); |
| 75 | assert(body.empty()); |
| 76 | const CService service = http_request.GetPeer(); |
| 77 | assert(service.ToString() == "[::]:0"); |
| 78 | |
| 79 | evbuffer_free(evbuf); |
| 80 | evhttp_request_free(evreq); |
| 81 | } |
nothing calls this directly
no test coverage detected