Skip to content

Commit bfef72d

Browse files
author
MarcoFalke
committed
Merge #18565: tests: Add fuzzing harnesses for classes/functions in policy/fees.h, checkqueue.h and cuckoocache.h. Add fuzzing coverage.
283bd72 tests: Add coverage of {,Incremental}DynamicUsage(const std::set<X, Y>& s) to existing fuzzer (practicalswift) bf76000 tests: Add fuzzing harness for classes/functions in cuckoocache.h (practicalswift) 57890b2 tests: Add fuzzing harness for classes/functions in checkqueue.h (practicalswift) 2df5701 tests: Add coverage of GetVirtualTransactionSize(...) to existing fuzzer (practicalswift) 7b9a2dc tests: Add fuzzing harness for AdditionOverflow(...) (practicalswift) 44fb2a5 tests: Add fuzzing harness for FeeFilterRounder (practicalswift) Pull request description: Includes: ``` tests: Add fuzzing harness for FeeFilterRounder tests: Add fuzzing harness for classes/functions in checkqueue.h tests: Add fuzzing harness for classes/functions in cuckoocache.h tests: Add coverage of {,Incremental}DynamicUsage(const std::set<X, Y>& s) to existing fuzzer tests: Add coverage of GetVirtualTransactionSize(...) to existing fuzzer tests: Add fuzzing harness for AdditionOverflow(...) ``` See [`doc/fuzzing.md`](https://github.com/bitcoin/bitcoin/blob/master/doc/fuzzing.md) for information on how to fuzz Bitcoin Core. ACKs for top commit: MarcoFalke: ACK 283bd72 Tree-SHA512: 2361edfb5c47741b22d9fb996836c5250c5a26bc5e956039ea6a0c55ba2d36c78f241d66f85bc02f5b85b9b83d5fde56a5c4702b9d1b7ac4a9a3ae391ca79eaa
2 parents 2392566 + 283bd72 commit bfef72d

File tree

8 files changed

+249
-2
lines changed

8 files changed

+249
-2
lines changed

src/Makefile.test.include

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
FUZZ_TARGETS = \
6+
test/fuzz/addition_overflow \
67
test/fuzz/addr_info_deserialize \
78
test/fuzz/addrdb \
89
test/fuzz/address_deserialize \
@@ -27,13 +28,16 @@ FUZZ_TARGETS = \
2728
test/fuzz/bloom_filter \
2829
test/fuzz/bloomfilter_deserialize \
2930
test/fuzz/chain \
31+
test/fuzz/checkqueue \
3032
test/fuzz/coins_deserialize \
33+
test/fuzz/cuckoocache \
3134
test/fuzz/decode_tx \
3235
test/fuzz/descriptor_parse \
3336
test/fuzz/diskblockindex_deserialize \
3437
test/fuzz/eval_script \
3538
test/fuzz/fee_rate \
3639
test/fuzz/fee_rate_deserialize \
40+
test/fuzz/fees \
3741
test/fuzz/flat_file_pos_deserialize \
3842
test/fuzz/flatfile \
3943
test/fuzz/float \
@@ -280,6 +284,12 @@ endif
280284

281285
if ENABLE_FUZZ
282286

287+
test_fuzz_addition_overflow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
288+
test_fuzz_addition_overflow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
289+
test_fuzz_addition_overflow_LDADD = $(FUZZ_SUITE_LD_COMMON)
290+
test_fuzz_addition_overflow_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
291+
test_fuzz_addition_overflow_SOURCES = test/fuzz/addition_overflow.cpp
292+
283293
test_fuzz_addr_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDR_INFO_DESERIALIZE=1
284294
test_fuzz_addr_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
285295
test_fuzz_addr_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
@@ -424,12 +434,24 @@ test_fuzz_chain_LDADD = $(FUZZ_SUITE_LD_COMMON)
424434
test_fuzz_chain_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
425435
test_fuzz_chain_SOURCES = test/fuzz/chain.cpp
426436

437+
test_fuzz_checkqueue_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
438+
test_fuzz_checkqueue_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
439+
test_fuzz_checkqueue_LDADD = $(FUZZ_SUITE_LD_COMMON)
440+
test_fuzz_checkqueue_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
441+
test_fuzz_checkqueue_SOURCES = test/fuzz/checkqueue.cpp
442+
427443
test_fuzz_coins_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DCOINS_DESERIALIZE=1
428444
test_fuzz_coins_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
429445
test_fuzz_coins_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
430446
test_fuzz_coins_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
431447
test_fuzz_coins_deserialize_SOURCES = test/fuzz/deserialize.cpp
432448

449+
test_fuzz_cuckoocache_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
450+
test_fuzz_cuckoocache_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
451+
test_fuzz_cuckoocache_LDADD = $(FUZZ_SUITE_LD_COMMON)
452+
test_fuzz_cuckoocache_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
453+
test_fuzz_cuckoocache_SOURCES = test/fuzz/cuckoocache.cpp
454+
433455
test_fuzz_decode_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
434456
test_fuzz_decode_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
435457
test_fuzz_decode_tx_LDADD = $(FUZZ_SUITE_LD_COMMON)
@@ -466,6 +488,12 @@ test_fuzz_fee_rate_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
466488
test_fuzz_fee_rate_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
467489
test_fuzz_fee_rate_deserialize_SOURCES = test/fuzz/deserialize.cpp
468490

491+
test_fuzz_fees_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
492+
test_fuzz_fees_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
493+
test_fuzz_fees_LDADD = $(FUZZ_SUITE_LD_COMMON)
494+
test_fuzz_fees_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
495+
test_fuzz_fees_SOURCES = test/fuzz/fees.cpp
496+
469497
test_fuzz_flat_file_pos_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DFLAT_FILE_POS_DESERIALIZE=1
470498
test_fuzz_flat_file_pos_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
471499
test_fuzz_flat_file_pos_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)

src/cuckoocache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#ifndef BITCOIN_CUCKOOCACHE_H
66
#define BITCOIN_CUCKOOCACHE_H
77

8+
#include <algorithm> // std::find
89
#include <array>
910
#include <atomic>
1011
#include <cmath>

src/test/fuzz/addition_overflow.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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 <test/fuzz/FuzzedDataProvider.h>
6+
#include <test/fuzz/fuzz.h>
7+
#include <test/fuzz/util.h>
8+
9+
#include <cstdint>
10+
#include <string>
11+
#include <vector>
12+
13+
#if defined(__has_builtin)
14+
#if __has_builtin(__builtin_add_overflow)
15+
#define HAVE_BUILTIN_ADD_OVERFLOW
16+
#endif
17+
#elif defined(__GNUC__) && (__GNUC__ >= 5)
18+
#define HAVE_BUILTIN_ADD_OVERFLOW
19+
#endif
20+
21+
namespace {
22+
template <typename T>
23+
void TestAdditionOverflow(FuzzedDataProvider& fuzzed_data_provider)
24+
{
25+
const T i = fuzzed_data_provider.ConsumeIntegral<T>();
26+
const T j = fuzzed_data_provider.ConsumeIntegral<T>();
27+
const bool is_addition_overflow_custom = AdditionOverflow(i, j);
28+
#if defined(HAVE_BUILTIN_ADD_OVERFLOW)
29+
T result_builtin;
30+
const bool is_addition_overflow_builtin = __builtin_add_overflow(i, j, &result_builtin);
31+
assert(is_addition_overflow_custom == is_addition_overflow_builtin);
32+
if (!is_addition_overflow_custom) {
33+
assert(i + j == result_builtin);
34+
}
35+
#else
36+
if (!is_addition_overflow_custom) {
37+
(void)(i + j);
38+
}
39+
#endif
40+
}
41+
} // namespace
42+
43+
void test_one_input(const std::vector<uint8_t>& buffer)
44+
{
45+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
46+
TestAdditionOverflow<int64_t>(fuzzed_data_provider);
47+
TestAdditionOverflow<uint64_t>(fuzzed_data_provider);
48+
TestAdditionOverflow<int32_t>(fuzzed_data_provider);
49+
TestAdditionOverflow<uint32_t>(fuzzed_data_provider);
50+
TestAdditionOverflow<int16_t>(fuzzed_data_provider);
51+
TestAdditionOverflow<uint16_t>(fuzzed_data_provider);
52+
TestAdditionOverflow<char>(fuzzed_data_provider);
53+
TestAdditionOverflow<unsigned char>(fuzzed_data_provider);
54+
TestAdditionOverflow<signed char>(fuzzed_data_provider);
55+
}

src/test/fuzz/checkqueue.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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 <checkqueue.h>
6+
#include <optional.h>
7+
#include <test/fuzz/FuzzedDataProvider.h>
8+
#include <test/fuzz/fuzz.h>
9+
#include <test/fuzz/util.h>
10+
11+
#include <cstdint>
12+
#include <string>
13+
#include <vector>
14+
15+
namespace {
16+
struct DumbCheck {
17+
const bool result = false;
18+
19+
DumbCheck() = default;
20+
21+
explicit DumbCheck(const bool _result) : result(_result)
22+
{
23+
}
24+
25+
bool operator()() const
26+
{
27+
return result;
28+
}
29+
30+
void swap(DumbCheck& x)
31+
{
32+
}
33+
};
34+
} // namespace
35+
36+
void test_one_input(const std::vector<uint8_t>& buffer)
37+
{
38+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
39+
40+
const unsigned int batch_size = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 1024);
41+
CCheckQueue<DumbCheck> check_queue_1{batch_size};
42+
CCheckQueue<DumbCheck> check_queue_2{batch_size};
43+
std::vector<DumbCheck> checks_1;
44+
std::vector<DumbCheck> checks_2;
45+
const int size = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 1024);
46+
for (int i = 0; i < size; ++i) {
47+
const bool result = fuzzed_data_provider.ConsumeBool();
48+
checks_1.emplace_back(result);
49+
checks_2.emplace_back(result);
50+
}
51+
if (fuzzed_data_provider.ConsumeBool()) {
52+
check_queue_1.Add(checks_1);
53+
}
54+
if (fuzzed_data_provider.ConsumeBool()) {
55+
(void)check_queue_1.Wait();
56+
}
57+
58+
CCheckQueueControl<DumbCheck> check_queue_control{&check_queue_2};
59+
if (fuzzed_data_provider.ConsumeBool()) {
60+
check_queue_control.Add(checks_2);
61+
}
62+
if (fuzzed_data_provider.ConsumeBool()) {
63+
(void)check_queue_control.Wait();
64+
}
65+
}

src/test/fuzz/cuckoocache.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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 <cuckoocache.h>
6+
#include <optional.h>
7+
#include <script/sigcache.h>
8+
#include <test/fuzz/FuzzedDataProvider.h>
9+
#include <test/fuzz/fuzz.h>
10+
#include <test/fuzz/util.h>
11+
#include <test/util/setup_common.h>
12+
13+
#include <cstdint>
14+
#include <string>
15+
#include <vector>
16+
17+
namespace {
18+
FuzzedDataProvider* fuzzed_data_provider_ptr = nullptr;
19+
20+
struct RandomHasher {
21+
template <uint8_t>
22+
uint32_t operator()(const bool& /* unused */) const
23+
{
24+
assert(fuzzed_data_provider_ptr != nullptr);
25+
return fuzzed_data_provider_ptr->ConsumeIntegral<uint32_t>();
26+
}
27+
};
28+
} // namespace
29+
30+
void test_one_input(const std::vector<uint8_t>& buffer)
31+
{
32+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
33+
fuzzed_data_provider_ptr = &fuzzed_data_provider;
34+
CuckooCache::cache<bool, RandomHasher> cuckoo_cache{};
35+
if (fuzzed_data_provider.ConsumeBool()) {
36+
const size_t megabytes = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 16);
37+
cuckoo_cache.setup_bytes(megabytes << 20);
38+
} else {
39+
cuckoo_cache.setup(fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, 4096));
40+
}
41+
while (fuzzed_data_provider.ConsumeBool()) {
42+
if (fuzzed_data_provider.ConsumeBool()) {
43+
cuckoo_cache.insert(fuzzed_data_provider.ConsumeBool());
44+
} else {
45+
cuckoo_cache.contains(fuzzed_data_provider.ConsumeBool(), fuzzed_data_provider.ConsumeBool());
46+
}
47+
}
48+
fuzzed_data_provider_ptr = nullptr;
49+
}

src/test/fuzz/fees.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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 <amount.h>
6+
#include <optional.h>
7+
#include <policy/fees.h>
8+
#include <test/fuzz/FuzzedDataProvider.h>
9+
#include <test/fuzz/fuzz.h>
10+
#include <test/fuzz/util.h>
11+
12+
#include <cstdint>
13+
#include <string>
14+
#include <vector>
15+
16+
void test_one_input(const std::vector<uint8_t>& buffer)
17+
{
18+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
19+
const CFeeRate minimal_incremental_fee{ConsumeMoney(fuzzed_data_provider)};
20+
FeeFilterRounder fee_filter_rounder{minimal_incremental_fee};
21+
while (fuzzed_data_provider.ConsumeBool()) {
22+
const CAmount current_minimum_fee = ConsumeMoney(fuzzed_data_provider);
23+
const CAmount rounded_fee = fee_filter_rounder.round(current_minimum_fee);
24+
assert(MoneyRange(rounded_fee));
25+
}
26+
}

src/test/fuzz/integer.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <streams.h>
2424
#include <test/fuzz/FuzzedDataProvider.h>
2525
#include <test/fuzz/fuzz.h>
26+
#include <test/fuzz/util.h>
2627
#include <time.h>
2728
#include <uint256.h>
2829
#include <util/moneystr.h>
@@ -35,6 +36,7 @@
3536
#include <cassert>
3637
#include <chrono>
3738
#include <limits>
39+
#include <set>
3840
#include <vector>
3941

4042
void initialize()
@@ -90,8 +92,12 @@ void test_one_input(const std::vector<uint8_t>& buffer)
9092
}
9193
(void)GetSizeOfCompactSize(u64);
9294
(void)GetSpecialScriptSize(u32);
93-
// (void)GetVirtualTransactionSize(i64, i64); // function defined only for a subset of int64_t inputs
94-
// (void)GetVirtualTransactionSize(i64, i64, u32); // function defined only for a subset of int64_t/uint32_t inputs
95+
if (!MultiplicationOverflow(i64, static_cast<int64_t>(::nBytesPerSigOp)) && !AdditionOverflow(i64 * ::nBytesPerSigOp, static_cast<int64_t>(4))) {
96+
(void)GetVirtualTransactionSize(i64, i64);
97+
}
98+
if (!MultiplicationOverflow(i64, static_cast<int64_t>(u32)) && !AdditionOverflow(i64, static_cast<int64_t>(4)) && !AdditionOverflow(i64 * u32, static_cast<int64_t>(4))) {
99+
(void)GetVirtualTransactionSize(i64, i64, u32);
100+
}
95101
(void)HexDigit(ch);
96102
(void)MoneyRange(i64);
97103
(void)ToString(i64);
@@ -109,6 +115,12 @@ void test_one_input(const std::vector<uint8_t>& buffer)
109115
(void)memusage::DynamicUsage(u8);
110116
const unsigned char uch = static_cast<unsigned char>(u8);
111117
(void)memusage::DynamicUsage(uch);
118+
{
119+
const std::set<int64_t> i64s{i64, static_cast<int64_t>(u64)};
120+
const size_t dynamic_usage = memusage::DynamicUsage(i64s);
121+
const size_t incremental_dynamic_usage = memusage::IncrementalDynamicUsage(i64s);
122+
assert(dynamic_usage == incremental_dynamic_usage * i64s.size());
123+
}
112124
(void)MillisToTimeval(i64);
113125
const double d = ser_uint64_to_double(u64);
114126
assert(ser_double_to_uint64(d) == u64);

src/test/fuzz/util.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,15 @@ NODISCARD bool MultiplicationOverflow(const T i, const T j) noexcept
120120
}
121121
}
122122

123+
template <class T>
124+
NODISCARD bool AdditionOverflow(const T i, const T j) noexcept
125+
{
126+
static_assert(std::is_integral<T>::value, "Integral required.");
127+
if (std::numeric_limits<T>::is_signed) {
128+
return (i > 0 && j > std::numeric_limits<T>::max() - i) ||
129+
(i < 0 && j < std::numeric_limits<T>::min() - i);
130+
}
131+
return std::numeric_limits<T>::max() - i < j;
132+
}
133+
123134
#endif // BITCOIN_TEST_FUZZ_UTIL_H

0 commit comments

Comments
 (0)