Skip to content

Commit a4153e2

Browse files
pstratemlaanwj
authored andcommitted
Simple fuzzing framework
1 parent b68685a commit a4153e2

File tree

4 files changed

+279
-0
lines changed

4 files changed

+279
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ src/bitcoind
66
src/bitcoin-cli
77
src/bitcoin-tx
88
src/test/test_bitcoin
9+
src/test/test_bitcoin_fuzzy
910
src/qt/test/test_bitcoin-qt
1011

1112
# autoreconf

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ EXTRA_LIBRARIES += \
6161
lib_LTLIBRARIES = $(LIBBITCOINCONSENSUS)
6262

6363
bin_PROGRAMS =
64+
noinst_PROGRAMS =
6465
TESTS =
6566
BENCHMARKS =
6667

src/Makefile.test.include

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
TESTS += test/test_bitcoin
66
bin_PROGRAMS += test/test_bitcoin
7+
noinst_PROGRAMS += test/test_bitcoin_fuzzy
78
TEST_SRCDIR = test
89
TEST_BINARY=test/test_bitcoin$(EXEEXT)
910

@@ -38,6 +39,7 @@ RAW_TEST_FILES =
3839

3940
GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
4041

42+
# test_bitcoin binary #
4143
BITCOIN_TESTS =\
4244
test/arith_uint256_tests.cpp \
4345
test/scriptnum10.h \
@@ -119,6 +121,25 @@ test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -s
119121
if ENABLE_ZMQ
120122
test_test_bitcoin_LDADD += $(ZMQ_LIBS)
121123
endif
124+
#
125+
126+
# test_bitcoin_fuzzy binary #
127+
test_test_bitcoin_fuzzy_SOURCES = test/test_bitcoin_fuzzy.cpp
128+
test_test_bitcoin_fuzzy_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
129+
test_test_bitcoin_fuzzy_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
130+
test_test_bitcoin_fuzzy_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
131+
132+
test_test_bitcoin_fuzzy_LDADD = \
133+
$(LIBUNIVALUE) \
134+
$(LIBBITCOIN_SERVER) \
135+
$(LIBBITCOIN_COMMON) \
136+
$(LIBBITCOIN_UTIL) \
137+
$(LIBBITCOIN_CONSENSUS) \
138+
$(LIBBITCOIN_CRYPTO) \
139+
$(LIBSECP256K1)
140+
141+
test_test_bitcoin_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
142+
#
122143

123144
nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
124145

src/test/test_bitcoin_fuzzy.cpp

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
// Copyright (c) 2009-2015 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+
#if defined(HAVE_CONFIG_H)
6+
#include "config/bitcoin-config.h"
7+
#endif
8+
9+
#include "consensus/merkle.h"
10+
#include "primitives/block.h"
11+
#include "script/script.h"
12+
#include "addrman.h"
13+
#include "chain.h"
14+
#include "coins.h"
15+
#include "compressor.h"
16+
#include "net.h"
17+
#include "protocol.h"
18+
#include "streams.h"
19+
#include "undo.h"
20+
#include "version.h"
21+
22+
#include <stdint.h>
23+
#include <unistd.h>
24+
25+
#include <algorithm>
26+
#include <vector>
27+
28+
enum TEST_ID {
29+
CBLOCK_DESERIALIZE=0,
30+
CTRANSACTION_DESERIALIZE,
31+
CBLOCKLOCATOR_DESERIALIZE,
32+
CBLOCKMERKLEROOT,
33+
CADDRMAN_DESERIALIZE,
34+
CBLOCKHEADER_DESERIALIZE,
35+
CBANENTRY_DESERIALIZE,
36+
CTXUNDO_DESERIALIZE,
37+
CBLOCKUNDO_DESERIALIZE,
38+
CCOINS_DESERIALIZE,
39+
CNETADDR_DESERIALIZE,
40+
CSERVICE_DESERIALIZE,
41+
CMESSAGEHEADER_DESERIALIZE,
42+
CADDRESS_DESERIALIZE,
43+
CINV_DESERIALIZE,
44+
CBLOOMFILTER_DESERIALIZE,
45+
CDISKBLOCKINDEX_DESERIALIZE,
46+
CTXOUTCOMPRESSOR_DESERIALIZE,
47+
TEST_ID_END
48+
};
49+
50+
bool read_stdin(std::vector<char> &data) {
51+
char buffer[1024];
52+
ssize_t length=0;
53+
while((length = read(STDIN_FILENO, buffer, 1024)) > 0) {
54+
data.insert(data.end(), buffer, buffer+length);
55+
56+
if (data.size() > (1<<20)) return false;
57+
}
58+
return length==0;
59+
}
60+
61+
int main(int argc, char **argv)
62+
{
63+
std::vector<char> buffer;
64+
if (!read_stdin(buffer)) return 0;
65+
66+
if (buffer.size() < sizeof(uint32_t)) return 0;
67+
68+
uint32_t test_id = 0xffffffff;
69+
memcpy(&test_id, &buffer[0], sizeof(uint32_t));
70+
buffer.erase(buffer.begin(), buffer.begin() + sizeof(uint32_t));
71+
72+
if (test_id >= TEST_ID_END) return 0;
73+
74+
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
75+
try {
76+
int nVersion;
77+
ds >> nVersion;
78+
ds.SetVersion(nVersion);
79+
} catch (const std::ios_base::failure& e) {
80+
return 0;
81+
}
82+
83+
switch(test_id) {
84+
case CBLOCK_DESERIALIZE:
85+
{
86+
try
87+
{
88+
CBlock block;
89+
ds >> block;
90+
} catch (const std::ios_base::failure& e) {return 0;}
91+
break;
92+
}
93+
case CTRANSACTION_DESERIALIZE:
94+
{
95+
try
96+
{
97+
CTransaction tx(deserialize, ds);
98+
} catch (const std::ios_base::failure& e) {return 0;}
99+
break;
100+
}
101+
case CBLOCKLOCATOR_DESERIALIZE:
102+
{
103+
try
104+
{
105+
CBlockLocator bl;
106+
ds >> bl;
107+
} catch (const std::ios_base::failure& e) {return 0;}
108+
break;
109+
}
110+
case CBLOCKMERKLEROOT:
111+
{
112+
try
113+
{
114+
CBlock block;
115+
ds >> block;
116+
bool mutated;
117+
BlockMerkleRoot(block, &mutated);
118+
} catch (const std::ios_base::failure& e) {return 0;}
119+
break;
120+
}
121+
case CADDRMAN_DESERIALIZE:
122+
{
123+
try
124+
{
125+
CAddrMan am;
126+
ds >> am;
127+
} catch (const std::ios_base::failure& e) {return 0;}
128+
break;
129+
}
130+
case CBLOCKHEADER_DESERIALIZE:
131+
{
132+
try
133+
{
134+
CBlockHeader bh;
135+
ds >> bh;
136+
} catch (const std::ios_base::failure& e) {return 0;}
137+
break;
138+
}
139+
case CBANENTRY_DESERIALIZE:
140+
{
141+
try
142+
{
143+
CBanEntry be;
144+
ds >> be;
145+
} catch (const std::ios_base::failure& e) {return 0;}
146+
break;
147+
}
148+
case CTXUNDO_DESERIALIZE:
149+
{
150+
try
151+
{
152+
CTxUndo tu;
153+
ds >> tu;
154+
} catch (const std::ios_base::failure& e) {return 0;}
155+
break;
156+
}
157+
case CBLOCKUNDO_DESERIALIZE:
158+
{
159+
try
160+
{
161+
CBlockUndo bu;
162+
ds >> bu;
163+
} catch (const std::ios_base::failure& e) {return 0;}
164+
break;
165+
}
166+
case CCOINS_DESERIALIZE:
167+
{
168+
try
169+
{
170+
CCoins block;
171+
ds >> block;
172+
} catch (const std::ios_base::failure& e) {return 0;}
173+
break;
174+
}
175+
case CNETADDR_DESERIALIZE:
176+
{
177+
try
178+
{
179+
CNetAddr na;
180+
ds >> na;
181+
} catch (const std::ios_base::failure& e) {return 0;}
182+
break;
183+
}
184+
case CSERVICE_DESERIALIZE:
185+
{
186+
try
187+
{
188+
CService s;
189+
ds >> s;
190+
} catch (const std::ios_base::failure& e) {return 0;}
191+
break;
192+
}
193+
case CMESSAGEHEADER_DESERIALIZE:
194+
{
195+
CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
196+
try
197+
{
198+
CMessageHeader mh(pchMessageStart);
199+
ds >> mh;
200+
if (!mh.IsValid(pchMessageStart)) {return 0;}
201+
} catch (const std::ios_base::failure& e) {return 0;}
202+
break;
203+
}
204+
case CADDRESS_DESERIALIZE:
205+
{
206+
try
207+
{
208+
CAddress a;
209+
ds >> a;
210+
} catch (const std::ios_base::failure& e) {return 0;}
211+
break;
212+
}
213+
case CINV_DESERIALIZE:
214+
{
215+
try
216+
{
217+
CInv i;
218+
ds >> i;
219+
} catch (const std::ios_base::failure& e) {return 0;}
220+
break;
221+
}
222+
case CBLOOMFILTER_DESERIALIZE:
223+
{
224+
try
225+
{
226+
CBloomFilter bf;
227+
ds >> bf;
228+
} catch (const std::ios_base::failure& e) {return 0;}
229+
break;
230+
}
231+
case CDISKBLOCKINDEX_DESERIALIZE:
232+
{
233+
try
234+
{
235+
CDiskBlockIndex dbi;
236+
ds >> dbi;
237+
} catch (const std::ios_base::failure& e) {return 0;}
238+
break;
239+
}
240+
case CTXOUTCOMPRESSOR_DESERIALIZE:
241+
{
242+
CTxOut to;
243+
try
244+
{
245+
ds >> to;
246+
} catch (const std::ios_base::failure& e) {return 0;}
247+
248+
CTxOutCompressor toc(to);
249+
break;
250+
}
251+
default:
252+
return 0;
253+
}
254+
return 0;
255+
}
256+

0 commit comments

Comments
 (0)