Skip to content

Commit 5560845

Browse files
committed
Make a fuzzer-based copy of the prevector randomized test
1 parent abc145c commit 5560845

File tree

2 files changed

+298
-0
lines changed

2 files changed

+298
-0
lines changed

src/Makefile.test.include

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ FUZZ_TARGETS = \
5858
test/fuzz/parse_numbers \
5959
test/fuzz/parse_script \
6060
test/fuzz/parse_univalue \
61+
test/fuzz/prevector \
6162
test/fuzz/partial_merkle_tree_deserialize \
6263
test/fuzz/partially_signed_transaction_deserialize \
6364
test/fuzz/pow \
@@ -609,6 +610,12 @@ test_fuzz_parse_univalue_LDADD = $(FUZZ_SUITE_LD_COMMON)
609610
test_fuzz_parse_univalue_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
610611
test_fuzz_parse_univalue_SOURCES = test/fuzz/parse_univalue.cpp
611612

613+
test_fuzz_prevector_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
614+
test_fuzz_prevector_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
615+
test_fuzz_prevector_LDADD = $(FUZZ_SUITE_LD_COMMON)
616+
test_fuzz_prevector_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
617+
test_fuzz_prevector_SOURCES = test/fuzz/prevector.cpp
618+
612619
test_fuzz_partial_merkle_tree_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPARTIAL_MERKLE_TREE_DESERIALIZE=1
613620
test_fuzz_partial_merkle_tree_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
614621
test_fuzz_partial_merkle_tree_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)

src/test/fuzz/prevector.cpp

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
// Copyright (c) 2015-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/fuzz.h>
6+
#include <test/fuzz/FuzzedDataProvider.h>
7+
8+
#include <vector>
9+
#include <prevector.h>
10+
11+
#include <reverse_iterator.h>
12+
#include <serialize.h>
13+
#include <streams.h>
14+
15+
namespace {
16+
17+
template<unsigned int N, typename T>
18+
class prevector_tester {
19+
typedef std::vector<T> realtype;
20+
realtype real_vector;
21+
realtype real_vector_alt;
22+
23+
typedef prevector<N, T> pretype;
24+
pretype pre_vector;
25+
pretype pre_vector_alt;
26+
27+
typedef typename pretype::size_type Size;
28+
bool passed = true;
29+
30+
template <typename A, typename B>
31+
void local_check_equal(A a, B b)
32+
{
33+
local_check(a == b);
34+
}
35+
36+
void local_check(bool b)
37+
{
38+
passed &= b;
39+
}
40+
void test() {
41+
const pretype& const_pre_vector = pre_vector;
42+
local_check_equal(real_vector.size(), pre_vector.size());
43+
local_check_equal(real_vector.empty(), pre_vector.empty());
44+
for (Size s = 0; s < real_vector.size(); s++) {
45+
local_check(real_vector[s] == pre_vector[s]);
46+
local_check(&(pre_vector[s]) == &(pre_vector.begin()[s]));
47+
local_check(&(pre_vector[s]) == &*(pre_vector.begin() + s));
48+
local_check(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size()));
49+
}
50+
// local_check(realtype(pre_vector) == real_vector);
51+
local_check(pretype(real_vector.begin(), real_vector.end()) == pre_vector);
52+
local_check(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector);
53+
size_t pos = 0;
54+
for (const T& v : pre_vector) {
55+
local_check(v == real_vector[pos++]);
56+
}
57+
for (const T& v : reverse_iterate(pre_vector)) {
58+
local_check(v == real_vector[--pos]);
59+
}
60+
for (const T& v : const_pre_vector) {
61+
local_check(v == real_vector[pos++]);
62+
}
63+
for (const T& v : reverse_iterate(const_pre_vector)) {
64+
local_check(v == real_vector[--pos]);
65+
}
66+
CDataStream ss1(SER_DISK, 0);
67+
CDataStream ss2(SER_DISK, 0);
68+
ss1 << real_vector;
69+
ss2 << pre_vector;
70+
local_check_equal(ss1.size(), ss2.size());
71+
for (Size s = 0; s < ss1.size(); s++) {
72+
local_check_equal(ss1[s], ss2[s]);
73+
}
74+
}
75+
76+
public:
77+
void resize(Size s) {
78+
real_vector.resize(s);
79+
local_check_equal(real_vector.size(), s);
80+
pre_vector.resize(s);
81+
local_check_equal(pre_vector.size(), s);
82+
test();
83+
}
84+
85+
void reserve(Size s) {
86+
real_vector.reserve(s);
87+
local_check(real_vector.capacity() >= s);
88+
pre_vector.reserve(s);
89+
local_check(pre_vector.capacity() >= s);
90+
test();
91+
}
92+
93+
void insert(Size position, const T& value) {
94+
real_vector.insert(real_vector.begin() + position, value);
95+
pre_vector.insert(pre_vector.begin() + position, value);
96+
test();
97+
}
98+
99+
void insert(Size position, Size count, const T& value) {
100+
real_vector.insert(real_vector.begin() + position, count, value);
101+
pre_vector.insert(pre_vector.begin() + position, count, value);
102+
test();
103+
}
104+
105+
template<typename I>
106+
void insert_range(Size position, I first, I last) {
107+
real_vector.insert(real_vector.begin() + position, first, last);
108+
pre_vector.insert(pre_vector.begin() + position, first, last);
109+
test();
110+
}
111+
112+
void erase(Size position) {
113+
real_vector.erase(real_vector.begin() + position);
114+
pre_vector.erase(pre_vector.begin() + position);
115+
test();
116+
}
117+
118+
void erase(Size first, Size last) {
119+
real_vector.erase(real_vector.begin() + first, real_vector.begin() + last);
120+
pre_vector.erase(pre_vector.begin() + first, pre_vector.begin() + last);
121+
test();
122+
}
123+
124+
void update(Size pos, const T& value) {
125+
real_vector[pos] = value;
126+
pre_vector[pos] = value;
127+
test();
128+
}
129+
130+
void push_back(const T& value) {
131+
real_vector.push_back(value);
132+
pre_vector.push_back(value);
133+
test();
134+
}
135+
136+
void pop_back() {
137+
real_vector.pop_back();
138+
pre_vector.pop_back();
139+
test();
140+
}
141+
142+
void clear() {
143+
real_vector.clear();
144+
pre_vector.clear();
145+
}
146+
147+
void assign(Size n, const T& value) {
148+
real_vector.assign(n, value);
149+
pre_vector.assign(n, value);
150+
}
151+
152+
Size size() const {
153+
return real_vector.size();
154+
}
155+
156+
Size capacity() const {
157+
return pre_vector.capacity();
158+
}
159+
160+
void shrink_to_fit() {
161+
pre_vector.shrink_to_fit();
162+
test();
163+
}
164+
165+
void swap() {
166+
real_vector.swap(real_vector_alt);
167+
pre_vector.swap(pre_vector_alt);
168+
test();
169+
}
170+
171+
void move() {
172+
real_vector = std::move(real_vector_alt);
173+
real_vector_alt.clear();
174+
pre_vector = std::move(pre_vector_alt);
175+
pre_vector_alt.clear();
176+
}
177+
178+
void copy() {
179+
real_vector = real_vector_alt;
180+
pre_vector = pre_vector_alt;
181+
}
182+
183+
void resize_uninitialized(realtype values) {
184+
size_t r = values.size();
185+
size_t s = real_vector.size() / 2;
186+
if (real_vector.capacity() < s + r) {
187+
real_vector.reserve(s + r);
188+
}
189+
real_vector.resize(s);
190+
pre_vector.resize_uninitialized(s);
191+
for (auto v : values) {
192+
real_vector.push_back(v);
193+
}
194+
auto p = pre_vector.size();
195+
pre_vector.resize_uninitialized(p + r);
196+
for (auto v : values) {
197+
pre_vector[p] = v;
198+
++p;
199+
}
200+
test();
201+
}
202+
203+
~prevector_tester() {
204+
assert(passed);
205+
}
206+
};
207+
208+
}
209+
210+
void test_one_input(const std::vector<uint8_t>& buffer)
211+
{
212+
FuzzedDataProvider prov(buffer.data(), buffer.size());
213+
prevector_tester<8, int> test;
214+
215+
while (prov.remaining_bytes()) {
216+
switch (prov.ConsumeIntegralInRange<int>(0, 14 + 3 * (test.size() > 0))) {
217+
case 0:
218+
test.insert(prov.ConsumeIntegralInRange<size_t>(0, test.size()), prov.ConsumeIntegral<int>());
219+
break;
220+
case 15:
221+
test.erase(prov.ConsumeIntegralInRange<size_t>(0, test.size() - 1));
222+
break;
223+
case 1:
224+
test.resize(std::max(0, std::min(30, (int)test.size() + prov.ConsumeIntegralInRange<int>(0, 4) - 2)));
225+
break;
226+
case 2:
227+
test.insert(prov.ConsumeIntegralInRange<size_t>(0, test.size()), 1 + prov.ConsumeBool(), prov.ConsumeIntegral<int>());
228+
break;
229+
case 3: {
230+
int del = std::min<int>(test.size(), 1 + prov.ConsumeBool());
231+
int beg = prov.ConsumeIntegralInRange<int>(0, test.size() - del);
232+
test.erase(beg, beg + del);
233+
break;
234+
}
235+
case 4:
236+
test.push_back(prov.ConsumeIntegral<int>());
237+
break;
238+
case 16:
239+
test.pop_back();
240+
break;
241+
case 5: {
242+
int values[4];
243+
int num = 1 + prov.ConsumeIntegralInRange<int>(0, 3);
244+
for (int k = 0; k < num; ++k) {
245+
values[k] = prov.ConsumeIntegral<int>();
246+
}
247+
test.insert_range(prov.ConsumeIntegralInRange<size_t>(0, test.size()), values, values + num);
248+
break;
249+
}
250+
case 6: {
251+
int del = std::min<int>(test.size(), 1 + prov.ConsumeIntegralInRange<int>(0, 3));
252+
int beg = prov.ConsumeIntegralInRange<int>(0, test.size() - del);
253+
test.erase(beg, beg + del);
254+
break;
255+
}
256+
case 7:
257+
test.reserve(prov.ConsumeIntegralInRange<size_t>(0, 32767));
258+
break;
259+
case 8:
260+
test.shrink_to_fit();
261+
break;
262+
case 17:
263+
test.update(prov.ConsumeIntegralInRange<size_t>(0, test.size() - 1), prov.ConsumeIntegral<int>());
264+
break;
265+
case 9:
266+
test.clear();
267+
break;
268+
case 10:
269+
test.assign(prov.ConsumeIntegralInRange<size_t>(0, 32767), prov.ConsumeIntegral<int>());
270+
break;
271+
case 11:
272+
test.swap();
273+
break;
274+
case 12:
275+
test.copy();
276+
break;
277+
case 13:
278+
test.move();
279+
break;
280+
case 14: {
281+
int num = 1 + prov.ConsumeIntegralInRange<int>(0, 15);
282+
std::vector<int> values(num);
283+
for (auto& v : values) {
284+
v = prov.ConsumeIntegral<int>();
285+
}
286+
test.resize_uninitialized(values);
287+
break;
288+
}
289+
}
290+
}
291+
}

0 commit comments

Comments
 (0)