Skip to content

Commit fab15ff

Browse files
author
MarcoFalke
committed
fuzz: Script validation flags
1 parent fabcfa5 commit fab15ff

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

src/Makefile.test.include

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ FUZZ_TARGETS = \
2121
test/fuzz/inv_deserialize \
2222
test/fuzz/messageheader_deserialize \
2323
test/fuzz/netaddr_deserialize \
24+
test/fuzz/script_flags \
2425
test/fuzz/service_deserialize \
2526
test/fuzz/transaction_deserialize \
2627
test/fuzz/txoutcompressor_deserialize \
@@ -358,6 +359,23 @@ test_fuzz_netaddr_deserialize_LDADD = \
358359
$(LIBSECP256K1)
359360
test_fuzz_netaddr_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
360361

362+
test_fuzz_script_flags_SOURCES = $(FUZZ_SUITE) test/fuzz/script_flags.cpp
363+
test_fuzz_script_flags_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
364+
test_fuzz_script_flags_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
365+
test_fuzz_script_flags_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
366+
test_fuzz_script_flags_LDADD = \
367+
$(LIBUNIVALUE) \
368+
$(LIBBITCOIN_SERVER) \
369+
$(LIBBITCOIN_COMMON) \
370+
$(LIBBITCOIN_UTIL) \
371+
$(LIBBITCOIN_CONSENSUS) \
372+
$(LIBBITCOIN_CRYPTO) \
373+
$(LIBBITCOIN_CRYPTO_SSE41) \
374+
$(LIBBITCOIN_CRYPTO_AVX2) \
375+
$(LIBBITCOIN_CRYPTO_SHANI) \
376+
$(LIBSECP256K1)
377+
test_fuzz_script_flags_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
378+
361379
test_fuzz_service_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
362380
test_fuzz_service_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSERVICE_DESERIALIZE=1
363381
test_fuzz_service_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)

src/test/fuzz/script_flags.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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+
#include <script/interpreter.h>
6+
#include <script/script.h>
7+
#include <streams.h>
8+
#include <version.h>
9+
10+
#include <test/fuzz/fuzz.h>
11+
12+
/** Flags that are not forbidden by an assert */
13+
static bool IsValidFlagCombination(unsigned flags);
14+
15+
void test_one_input(std::vector<uint8_t> buffer)
16+
{
17+
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
18+
try {
19+
int nVersion;
20+
ds >> nVersion;
21+
ds.SetVersion(nVersion);
22+
} catch (const std::ios_base::failure&) {
23+
return;
24+
}
25+
26+
try {
27+
const CTransaction tx(deserialize, ds);
28+
const PrecomputedTransactionData txdata(tx);
29+
30+
unsigned int verify_flags;
31+
ds >> verify_flags;
32+
33+
if (!IsValidFlagCombination(verify_flags)) return;
34+
35+
unsigned int fuzzed_flags;
36+
ds >> fuzzed_flags;
37+
38+
for (unsigned i = 0; i < tx.vin.size(); ++i) {
39+
CTxOut prevout;
40+
ds >> prevout;
41+
42+
const TransactionSignatureChecker checker{&tx, i, prevout.nValue, txdata};
43+
44+
ScriptError serror;
45+
const bool ret = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror);
46+
assert(ret == (serror == SCRIPT_ERR_OK));
47+
48+
// Verify that removing flags from a passing test or adding flags to a failing test does not change the result
49+
if (ret) {
50+
verify_flags &= ~fuzzed_flags;
51+
} else {
52+
verify_flags |= fuzzed_flags;
53+
}
54+
if (!IsValidFlagCombination(verify_flags)) return;
55+
56+
ScriptError serror_fuzzed;
57+
const bool ret_fuzzed = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror_fuzzed);
58+
assert(ret_fuzzed == (serror_fuzzed == SCRIPT_ERR_OK));
59+
60+
assert(ret_fuzzed == ret);
61+
}
62+
} catch (const std::ios_base::failure&) {
63+
return;
64+
}
65+
}
66+
67+
static bool IsValidFlagCombination(unsigned flags)
68+
{
69+
if (flags & SCRIPT_VERIFY_CLEANSTACK && ~flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) return false;
70+
if (flags & SCRIPT_VERIFY_WITNESS && ~flags & SCRIPT_VERIFY_P2SH) return false;
71+
return true;
72+
}

0 commit comments

Comments
 (0)