mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 04:22:55 +01:00
merge bitcoin#19259: Add fuzzing harness for LoadMempool(...) and DumpMempool(...)
This commit is contained in:
parent
30b9d66789
commit
11753e64e7
@ -321,7 +321,8 @@ test_fuzz_fuzz_SOURCES = \
|
||||
test/fuzz/timedata.cpp \
|
||||
test/fuzz/transaction.cpp \
|
||||
test/fuzz/tx_in.cpp \
|
||||
test/fuzz/tx_out.cpp
|
||||
test/fuzz/tx_out.cpp \
|
||||
test/fuzz/validation_load_mempool.cpp
|
||||
endif # ENABLE_FUZZ_BINARY
|
||||
|
||||
nodist_test_test_dash_SOURCES = $(GENERATED_TEST_FILES)
|
||||
|
@ -248,6 +248,16 @@ void SetFuzzedErrNo(FuzzedDataProvider& fuzzed_data_provider, const std::array<T
|
||||
errno = fuzzed_data_provider.PickValueInArray(errnos);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets a fuzzed errno in the range [0, 133 (EHWPOISON)]. Can be used from functions emulating
|
||||
* standard library functions that set errno, or in other contexts where the value of errno
|
||||
* might be relevant for the execution path that will be taken.
|
||||
*/
|
||||
inline void SetFuzzedErrNo(FuzzedDataProvider& fuzzed_data_provider) noexcept
|
||||
{
|
||||
errno = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 133);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a byte vector of specified size regardless of the number of remaining bytes available
|
||||
* from the fuzzer. Pads with zero value bytes if needed to achieve the specified size.
|
||||
@ -347,6 +357,7 @@ public:
|
||||
|
||||
FILE* open()
|
||||
{
|
||||
SetFuzzedErrNo(m_fuzzed_data_provider);
|
||||
if (m_fuzzed_data_provider.ConsumeBool()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -388,6 +399,7 @@ public:
|
||||
static ssize_t read(void* cookie, char* buf, size_t size)
|
||||
{
|
||||
FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie;
|
||||
SetFuzzedErrNo(fuzzed_file->m_fuzzed_data_provider);
|
||||
if (buf == nullptr || size == 0 || fuzzed_file->m_fuzzed_data_provider.ConsumeBool()) {
|
||||
return fuzzed_file->m_fuzzed_data_provider.ConsumeBool() ? 0 : -1;
|
||||
}
|
||||
@ -406,6 +418,7 @@ public:
|
||||
static ssize_t write(void* cookie, const char* buf, size_t size)
|
||||
{
|
||||
FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie;
|
||||
SetFuzzedErrNo(fuzzed_file->m_fuzzed_data_provider);
|
||||
const ssize_t n = fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<ssize_t>(0, size);
|
||||
if (AdditionOverflow(static_cast<ssize_t>(fuzzed_file->m_offset), n)) {
|
||||
return fuzzed_file->m_fuzzed_data_provider.ConsumeBool() ? 0 : -1;
|
||||
@ -416,8 +429,9 @@ public:
|
||||
|
||||
static int seek(void* cookie, int64_t* offset, int whence)
|
||||
{
|
||||
assert(whence == SEEK_SET || whence == SEEK_CUR); // SEEK_END not implemented yet.
|
||||
assert(whence == SEEK_SET || whence == SEEK_CUR || whence == SEEK_END);
|
||||
FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie;
|
||||
SetFuzzedErrNo(fuzzed_file->m_fuzzed_data_provider);
|
||||
int64_t new_offset = 0;
|
||||
if (whence == SEEK_SET) {
|
||||
new_offset = *offset;
|
||||
@ -426,6 +440,12 @@ public:
|
||||
return -1;
|
||||
}
|
||||
new_offset = fuzzed_file->m_offset + *offset;
|
||||
} else if (whence == SEEK_END) {
|
||||
const int64_t n = fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 4096);
|
||||
if (AdditionOverflow(n, *offset)) {
|
||||
return -1;
|
||||
}
|
||||
new_offset = n + *offset;
|
||||
}
|
||||
if (new_offset < 0) {
|
||||
return -1;
|
||||
@ -438,6 +458,7 @@ public:
|
||||
static int close(void* cookie)
|
||||
{
|
||||
FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie;
|
||||
SetFuzzedErrNo(fuzzed_file->m_fuzzed_data_provider);
|
||||
return fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<int>(-1, 0);
|
||||
}
|
||||
};
|
||||
|
34
src/test/fuzz/validation_load_mempool.cpp
Normal file
34
src/test/fuzz/validation_load_mempool.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2020 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 <chainparamsbase.h>
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <txmempool.h>
|
||||
#include <util/time.h>
|
||||
#include <validation.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
void initialize_validation_load_mempool()
|
||||
{
|
||||
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(validation_load_mempool, initialize_validation_load_mempool)
|
||||
{
|
||||
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
|
||||
SetMockTime(ConsumeTime(fuzzed_data_provider));
|
||||
FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider);
|
||||
|
||||
CTxMemPool pool{};
|
||||
auto fuzzed_fopen = [&](const fs::path&, const char*) {
|
||||
return fuzzed_file_provider.open();
|
||||
};
|
||||
(void)LoadMempool(pool, ::ChainstateActive(), fuzzed_fopen);
|
||||
(void)DumpMempool(pool, fuzzed_fopen, true);
|
||||
}
|
@ -5507,11 +5507,11 @@ CBlockFileInfo* GetBlockFileInfo(size_t n)
|
||||
|
||||
static const uint64_t MEMPOOL_DUMP_VERSION = 1;
|
||||
|
||||
bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate)
|
||||
bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate, FopenFn mockable_fopen_function)
|
||||
{
|
||||
const CChainParams& chainparams = Params();
|
||||
int64_t nExpiryTimeout = gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60;
|
||||
FILE* filestr = fsbridge::fopen(GetDataDir() / "mempool.dat", "rb");
|
||||
FILE* filestr{mockable_fopen_function(GetDataDir() / "mempool.dat", "rb")};
|
||||
CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
|
||||
if (file.IsNull()) {
|
||||
LogPrintf("Failed to open mempool file from disk. Continuing anyway.\n");
|
||||
@ -5601,7 +5601,7 @@ bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DumpMempool(const CTxMemPool& pool)
|
||||
bool DumpMempool(const CTxMemPool& pool, FopenFn mockable_fopen_function, bool skip_file_commit)
|
||||
{
|
||||
int64_t start = GetTimeMicros();
|
||||
|
||||
@ -5624,7 +5624,7 @@ bool DumpMempool(const CTxMemPool& pool)
|
||||
int64_t mid = GetTimeMicros();
|
||||
|
||||
try {
|
||||
FILE* filestr = fsbridge::fopen(GetDataDir() / "mempool.dat.new", "wb");
|
||||
FILE* filestr{mockable_fopen_function(GetDataDir() / "mempool.dat.new", "wb")};
|
||||
if (!filestr) {
|
||||
return false;
|
||||
}
|
||||
@ -5647,7 +5647,7 @@ bool DumpMempool(const CTxMemPool& pool)
|
||||
LogPrintf("Writing %d unbroadcast transactions to disk.\n", unbroadcast_txids.size());
|
||||
file << unbroadcast_txids;
|
||||
|
||||
if (!FileCommit(file.Get()))
|
||||
if (!skip_file_commit && !FileCommit(file.Get()))
|
||||
throw std::runtime_error("FileCommit failed");
|
||||
file.fclose();
|
||||
if (!RenameOver(GetDataDir() / "mempool.dat.new", GetDataDir() / "mempool.dat")) {
|
||||
|
@ -1087,11 +1087,13 @@ bool GetBlockHash(uint256& hashRet, int nBlockHeight = -1);
|
||||
/** Get block file info entry for one block file */
|
||||
CBlockFileInfo* GetBlockFileInfo(size_t n);
|
||||
|
||||
using FopenFn = std::function<FILE*(const fs::path&, const char*)>;
|
||||
|
||||
/** Dump the mempool to disk. */
|
||||
bool DumpMempool(const CTxMemPool& pool);
|
||||
bool DumpMempool(const CTxMemPool& pool, FopenFn mockable_fopen_function = fsbridge::fopen, bool skip_file_commit = false);
|
||||
|
||||
/** Load the mempool from disk. */
|
||||
bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate);
|
||||
bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate, FopenFn mockable_fopen_function = fsbridge::fopen);
|
||||
|
||||
//! Check whether the block associated with this index entry is pruned or not.
|
||||
inline bool IsBlockPruned(const CBlockIndex* pblockindex)
|
||||
|
Loading…
Reference in New Issue
Block a user