0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-21 12:22:50 -05:00
bitcoin-bitcoin-core/src/test/fuzz/http_request.cpp
Andrew Chow 35fbc97208
Merge bitcoin/bitcoin#25619: net: avoid overriding non-virtual ToString() in CService and use better naming
c9d548c91f net: remove CService::ToStringPort() (Vasil Dimov)
fd4f0f41e9 gui: simplify OptionsDialog::updateDefaultProxyNets() (Vasil Dimov)
96c791dd20 net: remove CService::ToString() use ToStringAddrPort() instead (Vasil Dimov)
944a9de08a net: remove CNetAddr::ToString() and use ToStringAddr() instead (Vasil Dimov)
043b9de59a scripted-diff: rename ToStringIP[Port]() to ToStringAddr[Port]() (Vasil Dimov)

Pull request description:

  Before this PR we had the somewhat confusing combination of methods:

  `CNetAddr::ToStringIP()`
  `CNetAddr::ToString()` (duplicate of the above)
  `CService::ToStringIPPort()`
  `CService::ToString()` (duplicate of the above, overrides a non-virtual method from `CNetAddr`)
  `CService::ToStringPort()`

  Avoid [overriding non-virtual methods](https://github.com/bitcoin/bitcoin/pull/25349/#issuecomment-1185226396).

  "IP" stands for "Internet Protocol" and while sometimes "IP addresses" are called just "IPs", it is incorrect to call Tor or I2P addresses "IPs". Thus use "Addr" instead of "IP".

  Change the above to:

  `CNetAddr::ToStringAddr()`
  `CService::ToStringAddrPort()`

  The changes touch a lot of files, but are mostly mechanical.

ACKs for top commit:
  sipa:
    utACK c9d548c91f
  achow101:
    ACK c9d548c91f
  jonatack:
    re-ACK c9d548c91f only change since my previous reviews is rebase, but as a sanity check rebased to current master and at each commit quickly re-reviewed and re-verified clean build and green unit tests
  LarryRuane:
    ACK c9d548c91f

Tree-SHA512: 633fb044bdecf9f551b5e3314c385bf10e2b78e8027dc51ec324b66b018da35e5b01f3fbe6295bbc455ea1bcd1a3629de1918d28de510693afaf6a52693f2157
2023-02-17 13:34:40 -05:00

66 lines
2.9 KiB
C++

// Copyright (c) 2020-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <httpserver.h>
#include <netaddress.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <util/strencodings.h>
#include <event2/buffer.h>
#include <event2/event.h>
#include <event2/http.h>
#include <event2/http_struct.h>
#include <cassert>
#include <cstdint>
#include <string>
#include <vector>
extern "C" int evhttp_parse_firstline_(struct evhttp_request*, struct evbuffer*);
extern "C" int evhttp_parse_headers_(struct evhttp_request*, struct evbuffer*);
std::string RequestMethodString(HTTPRequest::RequestMethod m);
FUZZ_TARGET(http_request)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
evhttp_request* evreq = evhttp_request_new(nullptr, nullptr);
assert(evreq != nullptr);
evreq->kind = EVHTTP_REQUEST;
evbuffer* evbuf = evbuffer_new();
assert(evbuf != nullptr);
const std::vector<uint8_t> http_buffer = ConsumeRandomLengthByteVector(fuzzed_data_provider, 4096);
evbuffer_add(evbuf, http_buffer.data(), http_buffer.size());
// 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(std::string{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) {
evbuffer_free(evbuf);
evhttp_request_free(evreq);
return;
}
HTTPRequest http_request{evreq, true};
const HTTPRequest::RequestMethod request_method = http_request.GetRequestMethod();
(void)RequestMethodString(request_method);
(void)http_request.GetURI();
(void)http_request.GetHeader("Host");
const std::string header = fuzzed_data_provider.ConsumeRandomLengthString(16);
(void)http_request.GetHeader(header);
(void)http_request.WriteHeader(header, fuzzed_data_provider.ConsumeRandomLengthString(16));
(void)http_request.GetHeader(header);
const std::string body = http_request.ReadBody();
assert(body.empty());
const CService service = http_request.GetPeer();
assert(service.ToStringAddrPort() == "[::]:0");
evbuffer_free(evbuf);
evhttp_request_free(evreq);
}