test: Build fuzz targets into seperate executables

This commit is contained in:
MarcoFalke
2019-01-25 18:35:36 -05:00
parent fab4bed68a
commit 2ca632e5b4
7 changed files with 504 additions and 218 deletions

View File

@@ -2,10 +2,6 @@
// 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 <addrman.h>
#include <blockencodings.h>
#include <chain.h>
@@ -28,54 +24,10 @@
#include <memory>
#include <vector>
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
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;
}
#include <test/fuzz/fuzz.h>
void test_one_input(std::vector<uint8_t> buffer)
{
if (buffer.size() < sizeof(uint32_t)) return;
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;
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
try {
int nVersion;
@@ -85,35 +37,24 @@ void test_one_input(std::vector<uint8_t> buffer)
return;
}
switch(test_id) {
case CBLOCK_DESERIALIZE:
{
#if BLOCK_DESERIALIZE
try
{
CBlock block;
ds >> block;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CTRANSACTION_DESERIALIZE:
{
#elif TRANSACTION_DESERIALIZE
try
{
CTransaction tx(deserialize, ds);
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CBLOCKLOCATOR_DESERIALIZE:
{
#elif BLOCKLOCATOR_DESERIALIZE
try
{
CBlockLocator bl;
ds >> bl;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CBLOCKMERKLEROOT:
{
#elif BLOCKMERKLEROOT
try
{
CBlock block;
@@ -121,82 +62,55 @@ void test_one_input(std::vector<uint8_t> buffer)
bool mutated;
BlockMerkleRoot(block, &mutated);
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CADDRMAN_DESERIALIZE:
{
#elif ADDRMAN_DESERIALIZE
try
{
CAddrMan am;
ds >> am;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CBLOCKHEADER_DESERIALIZE:
{
#elif BLOCKHEADER_DESERIALIZE
try
{
CBlockHeader bh;
ds >> bh;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CBANENTRY_DESERIALIZE:
{
#elif BANENTRY_DESERIALIZE
try
{
CBanEntry be;
ds >> be;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CTXUNDO_DESERIALIZE:
{
#elif TXUNDO_DESERIALIZE
try
{
CTxUndo tu;
ds >> tu;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CBLOCKUNDO_DESERIALIZE:
{
#elif BLOCKUNDO_DESERIALIZE
try
{
CBlockUndo bu;
ds >> bu;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CCOINS_DESERIALIZE:
{
#elif COINS_DESERIALIZE
try
{
Coin coin;
ds >> coin;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CNETADDR_DESERIALIZE:
{
#elif NETADDR_DESERIALIZE
try
{
CNetAddr na;
ds >> na;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CSERVICE_DESERIALIZE:
{
#elif SERVICE_DESERIALIZE
try
{
CService s;
ds >> s;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CMESSAGEHEADER_DESERIALIZE:
{
#elif MESSAGEHEADER_DESERIALIZE
CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
try
{
@@ -204,130 +118,50 @@ void test_one_input(std::vector<uint8_t> buffer)
ds >> mh;
if (!mh.IsValid(pchMessageStart)) {return;}
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CADDRESS_DESERIALIZE:
{
#elif ADDRESS_DESERIALIZE
try
{
CAddress a;
ds >> a;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CINV_DESERIALIZE:
{
#elif INV_DESERIALIZE
try
{
CInv i;
ds >> i;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CBLOOMFILTER_DESERIALIZE:
{
#elif BLOOMFILTER_DESERIALIZE
try
{
CBloomFilter bf;
ds >> bf;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CDISKBLOCKINDEX_DESERIALIZE:
{
#elif DISKBLOCKINDEX_DESERIALIZE
try
{
CDiskBlockIndex dbi;
ds >> dbi;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case CTXOUTCOMPRESSOR_DESERIALIZE:
{
#elif TXOUTCOMPRESSOR_DESERIALIZE
CTxOut to;
CTxOutCompressor toc(to);
try
{
ds >> toc;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case BLOCKTRANSACTIONS_DESERIALIZE:
{
#elif BLOCKTRANSACTIONS_DESERIALIZE
try
{
BlockTransactions bt;
ds >> bt;
} catch (const std::ios_base::failure& e) {return;}
break;
}
case BLOCKTRANSACTIONSREQUEST_DESERIALIZE:
{
#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
try
{
BlockTransactionsRequest btr;
ds >> btr;
} catch (const std::ios_base::failure& e) {return;}
break;
}
default:
return;
}
return;
}
void initialize()
{
const static auto verify_handle = MakeUnique<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.
while (__AFL_LOOP(1000)) {
std::vector<uint8_t> buffer;
if (!read_stdin(buffer)) {
continue;
}
test_one_input(buffer);
}
#else
std::vector<uint8_t> buffer;
if (!read_stdin(buffer)) {
return 0;
}
test_one_input(buffer);
#error Need at least one fuzz target to compile
#endif
}