mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-02 09:15:04 +02:00
Merge bitcoin/bitcoin#28584: Fuzz: extend CConnman tests
0802398e74fuzz: make it possible to mock (fuzz) CThreadInterrupt (Vasil Dimov)6d9e5d130dfuzz: add CConnman::SocketHandler() to the tests (Vasil Dimov)3265df63a4fuzz: add CConnman::InitBinds() to the tests (Vasil Dimov)91cbf4dbd8fuzz: add CConnman::CreateNodeFromAcceptedSocket() to the tests (Vasil Dimov)50da7432ecfuzz: add CConnman::OpenNetworkConnection() to the tests (Vasil Dimov)e6a917c8f8fuzz: add Fuzzed NetEventsInterface and use it in connman tests (Vasil Dimov)e883b37768fuzz: set the output argument of FuzzedSock::Accept() (Vasil Dimov) Pull request description: Extend `CConnman` fuzz tests to also exercise the methods `OpenNetworkConnection()`, `CreateNodeFromAcceptedSocket()`, `InitBinds()` and `SocketHandler()`. Previously fuzzing those methods would have resulted in real socket functions being called in the operating system which is undesirable during fuzzing. Now that https://github.com/bitcoin/bitcoin/pull/21878 is complete all those are mocked to a fuzzed socket and a fuzzed DNS resolver (see how `CreateSock` and `g_dns_lookup` are replaced in the first commit). ACKs for top commit: achow101: ACK0802398e74jonatack: Review re-ACK0802398e74dergoegge: Code review ACK0802398e74Tree-SHA512: a717d4e79f42bacf2b029c821fdc265e10e4e5c41af77cd4cb452cc5720ec83c62789d5b3dfafd39a22cc8c0500b18169aa7864d497dded729a32ab863dd6c4d
This commit is contained in:
@@ -7,6 +7,7 @@ add_library(test_fuzz STATIC EXCLUDE_FROM_ALL
|
||||
descriptor.cpp
|
||||
mempool.cpp
|
||||
net.cpp
|
||||
threadinterrupt.cpp
|
||||
../fuzz.cpp
|
||||
../util.cpp
|
||||
)
|
||||
|
||||
@@ -312,6 +312,33 @@ std::unique_ptr<Sock> FuzzedSock::Accept(sockaddr* addr, socklen_t* addr_len) co
|
||||
SetFuzzedErrNo(m_fuzzed_data_provider, accept_errnos);
|
||||
return std::unique_ptr<FuzzedSock>();
|
||||
}
|
||||
if (addr != nullptr) {
|
||||
// Set a fuzzed address in the output argument addr.
|
||||
memset(addr, 0x00, *addr_len);
|
||||
if (m_fuzzed_data_provider.ConsumeBool()) {
|
||||
// IPv4
|
||||
const socklen_t write_len = static_cast<socklen_t>(sizeof(sockaddr_in));
|
||||
if (*addr_len >= write_len) {
|
||||
*addr_len = write_len;
|
||||
auto addr4 = reinterpret_cast<sockaddr_in*>(addr);
|
||||
addr4->sin_family = AF_INET;
|
||||
const auto sin_addr_bytes = m_fuzzed_data_provider.ConsumeBytes<uint8_t>(sizeof(addr4->sin_addr));
|
||||
memcpy(&addr4->sin_addr, sin_addr_bytes.data(), sin_addr_bytes.size());
|
||||
addr4->sin_port = m_fuzzed_data_provider.ConsumeIntegralInRange<uint16_t>(1, 65535);
|
||||
}
|
||||
} else {
|
||||
// IPv6
|
||||
const socklen_t write_len = static_cast<socklen_t>(sizeof(sockaddr_in6));
|
||||
if (*addr_len >= write_len) {
|
||||
*addr_len = write_len;
|
||||
auto addr6 = reinterpret_cast<sockaddr_in6*>(addr);
|
||||
addr6->sin6_family = AF_INET6;
|
||||
const auto sin_addr_bytes = m_fuzzed_data_provider.ConsumeBytes<uint8_t>(sizeof(addr6->sin6_addr));
|
||||
memcpy(&addr6->sin6_addr, sin_addr_bytes.data(), sin_addr_bytes.size());
|
||||
addr6->sin6_port = m_fuzzed_data_provider.ConsumeIntegralInRange<uint16_t>(1, 65535);
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::make_unique<FuzzedSock>(m_fuzzed_data_provider);
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,25 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class FuzzedNetEvents : public NetEventsInterface
|
||||
{
|
||||
public:
|
||||
FuzzedNetEvents(FuzzedDataProvider& fdp) : m_fdp(fdp) {}
|
||||
|
||||
virtual void InitializeNode(const CNode&, ServiceFlags) override {}
|
||||
|
||||
virtual void FinalizeNode(const CNode&) override {}
|
||||
|
||||
virtual bool HasAllDesirableServiceFlags(ServiceFlags) const override { return m_fdp.ConsumeBool(); }
|
||||
|
||||
virtual bool ProcessMessages(CNode*, std::atomic<bool>&) override { return m_fdp.ConsumeBool(); }
|
||||
|
||||
virtual bool SendMessages(CNode*) override { return m_fdp.ConsumeBool(); }
|
||||
|
||||
private:
|
||||
FuzzedDataProvider& m_fdp;
|
||||
};
|
||||
|
||||
class FuzzedSock : public Sock
|
||||
{
|
||||
FuzzedDataProvider& m_fuzzed_data_provider;
|
||||
@@ -203,6 +222,11 @@ public:
|
||||
bool IsConnected(std::string& errmsg) const override;
|
||||
};
|
||||
|
||||
[[nodiscard]] inline FuzzedNetEvents ConsumeNetEvents(FuzzedDataProvider& fdp) noexcept
|
||||
{
|
||||
return FuzzedNetEvents{fdp};
|
||||
}
|
||||
|
||||
[[nodiscard]] inline FuzzedSock ConsumeSock(FuzzedDataProvider& fuzzed_data_provider)
|
||||
{
|
||||
return FuzzedSock{fuzzed_data_provider};
|
||||
@@ -225,6 +249,18 @@ inline CService ConsumeService(FuzzedDataProvider& fuzzed_data_provider) noexcep
|
||||
return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
|
||||
}
|
||||
|
||||
inline std::vector<CService> ConsumeServiceVector(FuzzedDataProvider& fuzzed_data_provider,
|
||||
size_t max_vector_size = 5) noexcept
|
||||
{
|
||||
std::vector<CService> ret;
|
||||
const size_t size = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size);
|
||||
ret.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
ret.emplace_back(ConsumeService(fuzzed_data_provider));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept;
|
||||
|
||||
template <bool ReturnUniquePtr = false>
|
||||
|
||||
22
src/test/fuzz/util/threadinterrupt.cpp
Normal file
22
src/test/fuzz/util/threadinterrupt.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2024-present 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 <test/fuzz/util.h>
|
||||
#include <test/fuzz/util/threadinterrupt.h>
|
||||
|
||||
FuzzedThreadInterrupt::FuzzedThreadInterrupt(FuzzedDataProvider& fuzzed_data_provider)
|
||||
: m_fuzzed_data_provider{fuzzed_data_provider}
|
||||
{
|
||||
}
|
||||
|
||||
bool FuzzedThreadInterrupt::interrupted() const
|
||||
{
|
||||
return m_fuzzed_data_provider.ConsumeBool();
|
||||
}
|
||||
|
||||
bool FuzzedThreadInterrupt::sleep_for(Clock::duration)
|
||||
{
|
||||
SetMockTime(ConsumeTime(m_fuzzed_data_provider)); // Time could go backwards.
|
||||
return m_fuzzed_data_provider.ConsumeBool();
|
||||
}
|
||||
33
src/test/fuzz/util/threadinterrupt.h
Normal file
33
src/test/fuzz/util/threadinterrupt.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2024-present The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_TEST_FUZZ_UTIL_THREADINTERRUPT_H
|
||||
#define BITCOIN_TEST_FUZZ_UTIL_THREADINTERRUPT_H
|
||||
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <util/threadinterrupt.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* Mocked CThreadInterrupt that returns "randomly" whether it is interrupted and never sleeps.
|
||||
*/
|
||||
class FuzzedThreadInterrupt : public CThreadInterrupt
|
||||
{
|
||||
public:
|
||||
explicit FuzzedThreadInterrupt(FuzzedDataProvider& fuzzed_data_provider);
|
||||
|
||||
virtual bool interrupted() const override;
|
||||
virtual bool sleep_for(Clock::duration) override;
|
||||
|
||||
private:
|
||||
FuzzedDataProvider& m_fuzzed_data_provider;
|
||||
};
|
||||
|
||||
[[nodiscard]] inline std::shared_ptr<CThreadInterrupt> ConsumeThreadInterrupt(FuzzedDataProvider& fuzzed_data_provider)
|
||||
{
|
||||
return std::make_shared<FuzzedThreadInterrupt>(fuzzed_data_provider);
|
||||
}
|
||||
|
||||
#endif // BITCOIN_TEST_FUZZ_UTIL_THREADINTERRUPT_H
|
||||
Reference in New Issue
Block a user