Skip to content

Commit 21dba16

Browse files
practicalswiftFabcien
authored andcommitted
tests: Add fuzzing harness for functions/classes in flatfile.h, merkleblock.h, random.h, serialize.h and span.h
Summary: ``` - Add fuzzing harness for functions/classes in flatfile.h - Add fuzzing harness for functions/classes in merkleblock.h - Add fuzzing harness for functions/classes in span.h - Add fuzzing harness for LimitedString (serialize.h) - Add fuzzing harness for functions/classes in random.h ``` Backport of core [[bitcoin/bitcoin#18455 | PR18455]]. Depends on D8979. Test Plan: ninja bitcoin-fuzzers ./test/fuzz/test_runner.py <path_to_corpus> Reviewers: #bitcoin_abc, PiRK Reviewed By: #bitcoin_abc, PiRK Subscribers: PiRK Differential Revision: https://reviews.bitcoinabc.org/D8981
1 parent 3297680 commit 21dba16

8 files changed

+199
-9
lines changed

src/random.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,10 @@ class FastRandomContext {
179179
}
180180
}
181181

182-
/** Generate a random integer in the range [0..range). */
182+
/**
183+
* Generate a random integer in the range [0..range).
184+
* Precondition: range > 0.
185+
*/
183186
uint64_t randrange(uint64_t range) noexcept {
184187
assert(range);
185188
--range;

src/test/fuzz/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,14 @@ add_regular_fuzz_targets(
8787
descriptor_parse
8888
eval_script
8989
fee_rate
90+
flatfile
9091
float
9192
hex
9293
integer
9394
key
9495
key_io
9596
locale
97+
merkleblock
9698
multiplication_overflow
9799
net_permissions
98100
netaddress
@@ -106,12 +108,14 @@ add_regular_fuzz_targets(
106108
process_messages
107109
protocol
108110
psbt
111+
random
109112
rolling_bloom_filter
110113
script
111114
script_flags
112115
script_ops
113116
scriptnum_ops
114117
signature_checker
118+
span
115119
spanparsing
116120
string
117121
strprintf

src/test/fuzz/flatfile.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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 <flatfile.h>
6+
7+
#include <test/fuzz/FuzzedDataProvider.h>
8+
#include <test/fuzz/fuzz.h>
9+
#include <test/fuzz/util.h>
10+
11+
#include <cassert>
12+
#include <cstdint>
13+
#include <optional>
14+
#include <string>
15+
#include <vector>
16+
17+
void test_one_input(const std::vector<uint8_t> &buffer) {
18+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
19+
std::optional<FlatFilePos> flat_file_pos =
20+
ConsumeDeserializable<FlatFilePos>(fuzzed_data_provider);
21+
if (!flat_file_pos) {
22+
return;
23+
}
24+
std::optional<FlatFilePos> another_flat_file_pos =
25+
ConsumeDeserializable<FlatFilePos>(fuzzed_data_provider);
26+
if (another_flat_file_pos) {
27+
assert((*flat_file_pos == *another_flat_file_pos) !=
28+
(*flat_file_pos != *another_flat_file_pos));
29+
}
30+
(void)flat_file_pos->ToString();
31+
flat_file_pos->SetNull();
32+
assert(flat_file_pos->IsNull());
33+
}

src/test/fuzz/merkleblock.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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 <merkleblock.h>
6+
#include <uint256.h>
7+
8+
#include <test/fuzz/FuzzedDataProvider.h>
9+
#include <test/fuzz/fuzz.h>
10+
#include <test/fuzz/util.h>
11+
12+
#include <cstdint>
13+
#include <optional>
14+
#include <string>
15+
#include <vector>
16+
17+
void test_one_input(const std::vector<uint8_t> &buffer) {
18+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
19+
std::optional<CPartialMerkleTree> partial_merkle_tree =
20+
ConsumeDeserializable<CPartialMerkleTree>(fuzzed_data_provider);
21+
if (!partial_merkle_tree) {
22+
return;
23+
}
24+
(void)partial_merkle_tree->GetNumTransactions();
25+
std::vector<uint256> matches;
26+
std::vector<size_t> indices;
27+
(void)partial_merkle_tree->ExtractMatches(matches, indices);
28+
}

src/test/fuzz/random.cpp

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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 <random.h>
6+
7+
#include <test/fuzz/FuzzedDataProvider.h>
8+
#include <test/fuzz/fuzz.h>
9+
#include <test/fuzz/util.h>
10+
11+
#include <algorithm>
12+
#include <cstdint>
13+
#include <string>
14+
#include <vector>
15+
16+
void test_one_input(const std::vector<uint8_t> &buffer) {
17+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
18+
FastRandomContext fast_random_context{ConsumeUInt256(fuzzed_data_provider)};
19+
(void)fast_random_context.rand64();
20+
(void)fast_random_context.randbits(
21+
fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 64));
22+
(void)fast_random_context.randrange(
23+
fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(
24+
FastRandomContext::min() + 1, FastRandomContext::max()));
25+
(void)fast_random_context.randbytes(
26+
fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 1024));
27+
(void)fast_random_context.rand32();
28+
(void)fast_random_context.rand256();
29+
(void)fast_random_context.randbool();
30+
(void)fast_random_context();
31+
32+
std::vector<int64_t> integrals =
33+
ConsumeRandomLengthIntegralVector<int64_t>(fuzzed_data_provider);
34+
Shuffle(integrals.begin(), integrals.end(), fast_random_context);
35+
std::shuffle(integrals.begin(), integrals.end(), fast_random_context);
36+
}

src/test/fuzz/span.cpp

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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 <span.h>
6+
7+
#include <test/fuzz/FuzzedDataProvider.h>
8+
#include <test/fuzz/fuzz.h>
9+
#include <test/fuzz/util.h>
10+
11+
#include <cassert>
12+
#include <cstddef>
13+
#include <cstdint>
14+
#include <string>
15+
#include <vector>
16+
17+
void test_one_input(const std::vector<uint8_t> &buffer) {
18+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
19+
20+
std::string str = fuzzed_data_provider.ConsumeBytesAsString(32);
21+
const Span<const char> span = MakeSpan(str);
22+
(void)span.data();
23+
(void)span.begin();
24+
(void)span.end();
25+
if (span.size() > 0) {
26+
const std::ptrdiff_t idx =
27+
fuzzed_data_provider.ConsumeIntegralInRange<std::ptrdiff_t>(
28+
0U, span.size() - 1U);
29+
(void)span.first(idx);
30+
(void)span.last(idx);
31+
(void)span.subspan(idx);
32+
(void)span.subspan(idx, span.size() - idx);
33+
(void)span[idx];
34+
}
35+
36+
std::string another_str = fuzzed_data_provider.ConsumeBytesAsString(32);
37+
const Span<const char> another_span = MakeSpan(another_str);
38+
assert((span <= another_span) != (span > another_span));
39+
assert((span == another_span) != (span != another_span));
40+
assert((span >= another_span) != (span < another_span));
41+
}

src/test/fuzz/string.cpp

+34-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212
#include <rpc/server.h>
1313
#include <rpc/util.h>
1414
#include <script/descriptor.h>
15-
#include <test/fuzz/FuzzedDataProvider.h>
16-
#include <test/fuzz/fuzz.h>
17-
#include <test/fuzz/util.h>
15+
#include <serialize.h>
16+
#include <streams.h>
1817
#include <util/error.h>
1918
#include <util/message.h>
2019
#include <util/settings.h>
@@ -23,6 +22,11 @@
2322
#include <util/system.h>
2423
#include <util/translation.h>
2524
#include <util/url.h>
25+
#include <version.h>
26+
27+
#include <test/fuzz/FuzzedDataProvider.h>
28+
#include <test/fuzz/fuzz.h>
29+
#include <test/fuzz/util.h>
2630

2731
#include <cstdint>
2832
#include <string>
@@ -95,4 +99,31 @@ void test_one_input(const std::vector<uint8_t> &buffer) {
9599
(void)urlDecode(random_string_1);
96100
(void)ValidAsCString(random_string_1);
97101
(void)_(random_string_1.c_str());
102+
103+
{
104+
CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
105+
std::string s;
106+
LimitedString<10> limited_string = LIMITED_STRING(s, 10);
107+
data_stream << random_string_1;
108+
try {
109+
data_stream >> limited_string;
110+
assert(data_stream.empty());
111+
assert(s.size() <= random_string_1.size());
112+
assert(s.size() <= 10);
113+
if (!random_string_1.empty()) {
114+
assert(!s.empty());
115+
}
116+
} catch (const std::ios_base::failure &) {
117+
}
118+
}
119+
{
120+
CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
121+
const LimitedString<10> limited_string =
122+
LIMITED_STRING(random_string_1, 10);
123+
data_stream << limited_string;
124+
std::string deserialized_string;
125+
data_stream >> deserialized_string;
126+
assert(data_stream.empty());
127+
assert(deserialized_string == random_string_1);
128+
}
98129
}

src/test/fuzz/util.h

+19-5
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@
2222

2323
NODISCARD inline std::vector<uint8_t>
2424
ConsumeRandomLengthByteVector(FuzzedDataProvider &fuzzed_data_provider,
25-
size_t max_length = 4096) noexcept {
25+
const size_t max_length = 4096) noexcept {
2626
const std::string s =
2727
fuzzed_data_provider.ConsumeRandomLengthString(max_length);
2828
return {s.begin(), s.end()};
2929
}
3030

3131
NODISCARD inline std::vector<std::string>
3232
ConsumeRandomLengthStringVector(FuzzedDataProvider &fuzzed_data_provider,
33-
size_t max_vector_size = 16,
34-
size_t max_string_length = 16) noexcept {
33+
const size_t max_vector_size = 16,
34+
const size_t max_string_length = 16) noexcept {
3535
const size_t n_elements =
3636
fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size);
3737
std::vector<std::string> r;
@@ -42,10 +42,23 @@ ConsumeRandomLengthStringVector(FuzzedDataProvider &fuzzed_data_provider,
4242
return r;
4343
}
4444

45+
template <typename T>
46+
NODISCARD inline std::vector<T>
47+
ConsumeRandomLengthIntegralVector(FuzzedDataProvider &fuzzed_data_provider,
48+
const size_t max_vector_size = 16) noexcept {
49+
const size_t n_elements =
50+
fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size);
51+
std::vector<T> r;
52+
for (size_t i = 0; i < n_elements; ++i) {
53+
r.push_back(fuzzed_data_provider.ConsumeIntegral<T>());
54+
}
55+
return r;
56+
}
57+
4558
template <typename T>
4659
NODISCARD inline std::optional<T>
4760
ConsumeDeserializable(FuzzedDataProvider &fuzzed_data_provider,
48-
size_t max_length = 4096) noexcept {
61+
const size_t max_length = 4096) noexcept {
4962
const std::vector<uint8_t> buffer =
5063
ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length);
5164
CDataStream ds{buffer, SER_NETWORK, INIT_PROTO_VERSION};
@@ -95,7 +108,8 @@ ConsumeUInt256(FuzzedDataProvider &fuzzed_data_provider) noexcept {
95108
return uint256{v256};
96109
}
97110

98-
template <typename T> bool MultiplicationOverflow(T i, T j) {
111+
template <typename T>
112+
NODISCARD bool MultiplicationOverflow(const T i, const T j) noexcept {
99113
static_assert(std::is_integral<T>::value, "Integral required.");
100114
if (std::numeric_limits<T>::is_signed) {
101115
if (i > 0) {

0 commit comments

Comments
 (0)