bitcoin/src/test/test_bitcoin_fuzzy.cpp
practicalswift c3f34d06be Make it clear which functions that are intended to be translation unit local
Do not share functions that are meant to be translation unit local with
other translation units. Use internal linkage for those consistently.
2018-05-03 21:47:40 +02:00

329 lines
8.3 KiB
C++

// Copyright (c) 2009-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif
#include <consensus/merkle.h>
#include <primitives/block.h>
#include <script/script.h>
#include <addrman.h>
#include <chain.h>
#include <coins.h>
#include <compressor.h>
#include <net.h>
#include <protocol.h>
#include <streams.h>
#include <undo.h>
#include <version.h>
#include <pubkey.h>
#include <blockencodings.h>
#include <stdint.h>
#include <unistd.h>
#include <algorithm>
#include <memory>
#include <vector>
enum TEST_ID {
CBLOCK_DESERIALIZE=0,
CTRANSACTION_DESERIALIZE,
CBLOCKLOCATOR_DESERIALIZE,
CBLOCKMERKLEROOT,
CADDRMAN_DESERIALIZE,
CBLOCKHEADER_DESERIALIZE,
CBANENTRY_DESERIALIZE,
CTXUNDO_DESERIALIZE,
CBLOCKUNDO_DESERIALIZE,
CCOINS_DESERIALIZE,
CNETADDR_DESERIALIZE,
CSERVICE_DESERIALIZE,
CMESSAGEHEADER_DESERIALIZE,
CADDRESS_DESERIALIZE,
CINV_DESERIALIZE,
CBLOOMFILTER_DESERIALIZE,
CDISKBLOCKINDEX_DESERIALIZE,
CTXOUTCOMPRESSOR_DESERIALIZE,
BLOCKTRANSACTIONS_DESERIALIZE,
BLOCKTRANSACTIONSREQUEST_DESERIALIZE,
TEST_ID_END
};
static bool read_stdin(std::vector<uint8_t> &data) {
uint8_t buffer[1024];
ssize_t length=0;
while((length = read(STDIN_FILENO, buffer, 1024)) > 0) {
data.insert(data.end(), buffer, buffer+length);
if (data.size() > (1<<20)) return false;
}
return length==0;
}
static int test_one_input(std::vector<uint8_t> buffer) {
if (buffer.size() < sizeof(uint32_t)) return 0;
uint32_t test_id = 0xffffffff;
memcpy(&test_id, buffer.data(), sizeof(uint32_t));
buffer.erase(buffer.begin(), buffer.begin() + sizeof(uint32_t));
if (test_id >= TEST_ID_END) return 0;
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
try {
int nVersion;
ds >> nVersion;
ds.SetVersion(nVersion);
} catch (const std::ios_base::failure& e) {
return 0;
}
switch(test_id) {
case CBLOCK_DESERIALIZE:
{
try
{
CBlock block;
ds >> block;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CTRANSACTION_DESERIALIZE:
{
try
{
CTransaction tx(deserialize, ds);
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CBLOCKLOCATOR_DESERIALIZE:
{
try
{
CBlockLocator bl;
ds >> bl;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CBLOCKMERKLEROOT:
{
try
{
CBlock block;
ds >> block;
bool mutated;
BlockMerkleRoot(block, &mutated);
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CADDRMAN_DESERIALIZE:
{
try
{
CAddrMan am;
ds >> am;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CBLOCKHEADER_DESERIALIZE:
{
try
{
CBlockHeader bh;
ds >> bh;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CBANENTRY_DESERIALIZE:
{
try
{
CBanEntry be;
ds >> be;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CTXUNDO_DESERIALIZE:
{
try
{
CTxUndo tu;
ds >> tu;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CBLOCKUNDO_DESERIALIZE:
{
try
{
CBlockUndo bu;
ds >> bu;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CCOINS_DESERIALIZE:
{
try
{
Coin coin;
ds >> coin;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CNETADDR_DESERIALIZE:
{
try
{
CNetAddr na;
ds >> na;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CSERVICE_DESERIALIZE:
{
try
{
CService s;
ds >> s;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CMESSAGEHEADER_DESERIALIZE:
{
CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
try
{
CMessageHeader mh(pchMessageStart);
ds >> mh;
if (!mh.IsValid(pchMessageStart)) {return 0;}
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CADDRESS_DESERIALIZE:
{
try
{
CAddress a;
ds >> a;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CINV_DESERIALIZE:
{
try
{
CInv i;
ds >> i;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CBLOOMFILTER_DESERIALIZE:
{
try
{
CBloomFilter bf;
ds >> bf;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CDISKBLOCKINDEX_DESERIALIZE:
{
try
{
CDiskBlockIndex dbi;
ds >> dbi;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CTXOUTCOMPRESSOR_DESERIALIZE:
{
CTxOut to;
CTxOutCompressor toc(to);
try
{
ds >> toc;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case BLOCKTRANSACTIONS_DESERIALIZE:
{
try
{
BlockTransactions bt;
ds >> bt;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case BLOCKTRANSACTIONSREQUEST_DESERIALIZE:
{
try
{
BlockTransactionsRequest btr;
ds >> btr;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
default:
return 0;
}
return 0;
}
static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle;
void initialize() {
globalVerifyHandle = std::unique_ptr<ECCVerifyHandle>(new ECCVerifyHandle());
}
// This function is used by libFuzzer
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
test_one_input(std::vector<uint8_t>(data, data + size));
return 0;
}
// This function is used by libFuzzer
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
initialize();
return 0;
}
// Disabled under WIN32 due to clash with Cygwin's WinMain.
#ifndef WIN32
// Declare main(...) "weak" to allow for libFuzzer linking. libFuzzer provides
// the main(...) function.
__attribute__((weak))
#endif
int main(int argc, char **argv)
{
initialize();
#ifdef __AFL_INIT
// Enable AFL deferred forkserver mode. Requires compilation using
// afl-clang-fast++. See fuzzing.md for details.
__AFL_INIT();
#endif
#ifdef __AFL_LOOP
// Enable AFL persistent mode. Requires compilation using afl-clang-fast++.
// See fuzzing.md for details.
int ret = 0;
while (__AFL_LOOP(1000)) {
std::vector<uint8_t> buffer;
if (!read_stdin(buffer)) {
continue;
}
ret = test_one_input(buffer);
}
return ret;
#else
std::vector<uint8_t> buffer;
if (!read_stdin(buffer)) {
return 0;
}
return test_one_input(buffer);
#endif
}