Skip to content

Commit 2a6a6ea

Browse files
tests: Add fuzzing harness for bloom filter class CBloomFilter
1 parent ab9de43 commit 2a6a6ea

File tree

4 files changed

+129
-1
lines changed

4 files changed

+129
-1
lines changed

src/Makefile.test.include

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ FUZZ_TARGETS = \
2222
test/fuzz/blocktransactions_deserialize \
2323
test/fuzz/blocktransactionsrequest_deserialize \
2424
test/fuzz/blockundo_deserialize \
25+
test/fuzz/bloom_filter \
2526
test/fuzz/bloomfilter_deserialize \
2627
test/fuzz/coins_deserialize \
2728
test/fuzz/decode_tx \
@@ -96,7 +97,8 @@ BITCOIN_TEST_SUITE = \
9697
FUZZ_SUITE = \
9798
test/fuzz/fuzz.cpp \
9899
test/fuzz/fuzz.h \
99-
test/fuzz/FuzzedDataProvider.h
100+
test/fuzz/FuzzedDataProvider.h \
101+
test/fuzz/util.h
100102

101103
FUZZ_SUITE_LD_COMMON = \
102104
$(LIBBITCOIN_SERVER) \
@@ -347,6 +349,12 @@ test_fuzz_blockundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
347349
test_fuzz_blockundo_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
348350
test_fuzz_blockundo_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
349351

352+
test_fuzz_bloom_filter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
353+
test_fuzz_bloom_filter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
354+
test_fuzz_bloom_filter_LDADD = $(FUZZ_SUITE_LD_COMMON)
355+
test_fuzz_bloom_filter_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
356+
test_fuzz_bloom_filter_SOURCES = $(FUZZ_SUITE) test/fuzz/bloom_filter.cpp
357+
350358
test_fuzz_bloomfilter_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOOMFILTER_DESERIALIZE=1
351359
test_fuzz_bloomfilter_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
352360
test_fuzz_bloomfilter_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)

src/test/fuzz/bloom_filter.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright (c) 2020 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <bloom.h>
6+
#include <optional.h>
7+
#include <primitives/transaction.h>
8+
#include <test/fuzz/FuzzedDataProvider.h>
9+
#include <test/fuzz/fuzz.h>
10+
#include <test/fuzz/util.h>
11+
#include <uint256.h>
12+
13+
#include <cassert>
14+
#include <cstdint>
15+
#include <string>
16+
#include <vector>
17+
18+
void test_one_input(const std::vector<uint8_t>& buffer)
19+
{
20+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
21+
22+
CBloomFilter bloom_filter{
23+
fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(1, 10000000),
24+
1.0 / fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(1, std::numeric_limits<unsigned int>::max()),
25+
fuzzed_data_provider.ConsumeIntegral<unsigned int>(),
26+
static_cast<unsigned char>(fuzzed_data_provider.PickValueInArray({BLOOM_UPDATE_NONE, BLOOM_UPDATE_ALL, BLOOM_UPDATE_P2PUBKEY_ONLY, BLOOM_UPDATE_MASK}))};
27+
while (fuzzed_data_provider.remaining_bytes() > 0) {
28+
switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 6)) {
29+
case 0: {
30+
const std::vector<unsigned char>& b = ConsumeRandomLengthByteVector(fuzzed_data_provider);
31+
(void)bloom_filter.contains(b);
32+
bloom_filter.insert(b);
33+
const bool present = bloom_filter.contains(b);
34+
assert(present);
35+
break;
36+
}
37+
case 1: {
38+
const Optional<COutPoint> out_point = ConsumeDeserializable<COutPoint>(fuzzed_data_provider);
39+
if (!out_point) {
40+
break;
41+
}
42+
(void)bloom_filter.contains(*out_point);
43+
bloom_filter.insert(*out_point);
44+
const bool present = bloom_filter.contains(*out_point);
45+
assert(present);
46+
break;
47+
}
48+
case 2: {
49+
const Optional<uint256> u256 = ConsumeDeserializable<uint256>(fuzzed_data_provider);
50+
if (!u256) {
51+
break;
52+
}
53+
(void)bloom_filter.contains(*u256);
54+
bloom_filter.insert(*u256);
55+
const bool present = bloom_filter.contains(*u256);
56+
assert(present);
57+
break;
58+
}
59+
case 3:
60+
bloom_filter.clear();
61+
break;
62+
case 4:
63+
bloom_filter.reset(fuzzed_data_provider.ConsumeIntegral<unsigned int>());
64+
break;
65+
case 5: {
66+
const Optional<CMutableTransaction> mut_tx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
67+
if (!mut_tx) {
68+
break;
69+
}
70+
const CTransaction tx{*mut_tx};
71+
(void)bloom_filter.IsRelevantAndUpdate(tx);
72+
break;
73+
}
74+
case 6:
75+
bloom_filter.UpdateEmptyFull();
76+
break;
77+
}
78+
(void)bloom_filter.IsWithinSizeConstraints();
79+
}
80+
}

src/test/fuzz/util.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) 2009-2019 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_TEST_FUZZ_UTIL_H
6+
#define BITCOIN_TEST_FUZZ_UTIL_H
7+
8+
#include <attributes.h>
9+
#include <optional.h>
10+
#include <serialize.h>
11+
#include <streams.h>
12+
#include <test/fuzz/FuzzedDataProvider.h>
13+
#include <version.h>
14+
15+
#include <cstdint>
16+
#include <string>
17+
#include <vector>
18+
19+
NODISCARD inline std::vector<uint8_t> ConsumeRandomLengthByteVector(FuzzedDataProvider& fuzzed_data_provider, size_t max_length = 4096) noexcept
20+
{
21+
const std::string s = fuzzed_data_provider.ConsumeRandomLengthString(max_length);
22+
return {s.begin(), s.end()};
23+
}
24+
25+
template <typename T>
26+
NODISCARD inline Optional<T> ConsumeDeserializable(FuzzedDataProvider& fuzzed_data_provider, size_t max_length = 4096) noexcept
27+
{
28+
const std::vector<uint8_t>& buffer = ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length);
29+
CDataStream ds{buffer, SER_NETWORK, INIT_PROTO_VERSION};
30+
T obj;
31+
try {
32+
ds >> obj;
33+
} catch (const std::ios_base::failure&) {
34+
return nullopt;
35+
}
36+
return obj;
37+
}
38+
39+
#endif // BITCOIN_TEST_FUZZ_UTIL_H

test/fuzz/test_runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"block_file_info_deserialize",
2222
"block_filter_deserialize",
2323
"block_header_and_short_txids_deserialize",
24+
"bloom_filter",
2425
"decode_tx",
2526
"fee_rate_deserialize",
2627
"flat_file_pos_deserialize",

0 commit comments

Comments
 (0)