Changeset View
Changeset View
Standalone View
Standalone View
src/test/fuzz/http_request.cpp
// Copyright (c) 2020 The Bitcoin Core developers | // Copyright (c) 2020 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <httpserver.h> | #include <httpserver.h> | ||||
#include <netaddress.h> | #include <netaddress.h> | ||||
#include <util/strencodings.h> | |||||
#include <test/fuzz/FuzzedDataProvider.h> | #include <test/fuzz/FuzzedDataProvider.h> | ||||
#include <test/fuzz/fuzz.h> | #include <test/fuzz/fuzz.h> | ||||
#include <test/fuzz/util.h> | #include <test/fuzz/util.h> | ||||
#include <event2/buffer.h> | #include <event2/buffer.h> | ||||
#include <event2/event.h> | #include <event2/event.h> | ||||
#include <event2/http.h> | #include <event2/http.h> | ||||
Show All 31 Lines | void test_one_input(const std::vector<uint8_t> &buffer) { | ||||
evhttp_request *evreq = evhttp_request_new(nullptr, nullptr); | evhttp_request *evreq = evhttp_request_new(nullptr, nullptr); | ||||
assert(evreq != nullptr); | assert(evreq != nullptr); | ||||
evreq->kind = EVHTTP_REQUEST; | evreq->kind = EVHTTP_REQUEST; | ||||
evbuffer *evbuf = evbuffer_new(); | evbuffer *evbuf = evbuffer_new(); | ||||
assert(evbuf != nullptr); | assert(evbuf != nullptr); | ||||
const std::vector<uint8_t> http_buffer = | const std::vector<uint8_t> http_buffer = | ||||
ConsumeRandomLengthByteVector(fuzzed_data_provider, 4096); | ConsumeRandomLengthByteVector(fuzzed_data_provider, 4096); | ||||
evbuffer_add(evbuf, http_buffer.data(), http_buffer.size()); | evbuffer_add(evbuf, http_buffer.data(), http_buffer.size()); | ||||
if (evhttp_parse_firstline_(evreq, evbuf) != 1 || | // Avoid constructing requests that will be interpreted by libevent as PROXY | ||||
// requests to avoid triggering a nullptr dereference. The dereference | |||||
// (req->evcon->http_server) takes place in evhttp_parse_request_line and is | |||||
// a consequence of our hacky but necessary use of the internal function | |||||
// evhttp_parse_firstline_ in this fuzzing harness. The workaround is not | |||||
// aesthetically pleasing, but it successfully avoids the troublesome code | |||||
// path. " http:// HTTP/1.1\n" was a crashing input prior to this | |||||
// workaround. | |||||
const std::string http_buffer_str = | |||||
ToLower({http_buffer.begin(), http_buffer.end()}); | |||||
if (http_buffer_str.find(" http://") != std::string::npos || | |||||
http_buffer_str.find(" https://") != std::string::npos || | |||||
evhttp_parse_firstline_(evreq, evbuf) != 1 || | |||||
evhttp_parse_headers_(evreq, evbuf) != 1) { | evhttp_parse_headers_(evreq, evbuf) != 1) { | ||||
evbuffer_free(evbuf); | evbuffer_free(evbuf); | ||||
evhttp_request_free(evreq); | evhttp_request_free(evreq); | ||||
return; | return; | ||||
} | } | ||||
HTTPRequest http_request{evreq, true}; | HTTPRequest http_request{evreq, true}; | ||||
const HTTPRequest::RequestMethod request_method = | const HTTPRequest::RequestMethod request_method = | ||||
Show All 18 Lines |