kevacoin/src/test/test_bitcoin_fuzzy.cpp
practicalswift 693247b82b [test] Speed up fuzzing by ~200x when using afl-fuzz
Enable the `afl-clang-fast++` features deferred forkserver (`__AFL_INIT`) and persistent mode (`__AFL_LOOP(1000)`).

Before this patch:

```
$ afl-fuzz -i input -o output -m512 -- src/test/test_bitcoin_fuzzy
[*] Validating target binary...
[!] WARNING: The target binary is pretty slow! See /usr/local/share/doc/afl/perf_tips.txt.
[+] Here are some useful stats:

    Test case count : 1 favored, 0 variable, 1 total
       Bitmap range : 1072 to 1072 bits (average: 1072.00 bits)
        Exec timing : 20.4k to 20.4k us (average: 20.4k us)
…
exec speed : 57.58/sec (slow!)
exec speed : 48.35/sec (slow!)
exec speed : 53.78/sec (slow!)
```

After this patch:

```
$ afl-fuzz -i input -o output -m512 -- src/test/test_bitcoin_fuzzy
[*] Validating target binary...
[+] Persistent mode binary detected.
[+] Deferred forkserver binary detected.
[+] Here are some useful stats:

    Test case count : 1 favored, 0 variable, 1 total
       Bitmap range : 24 to 24 bits (average: 24.00 bits)
        Exec timing : 114 to 114 us (average: 114 us)
…
exec speed : 15.9k/sec
exec speed : 13.1k/sec
exec speed : 15.1k/sec
```
2017-05-19 07:28:46 +02:00

278 lines
6.8 KiB
C++

// Copyright (c) 2009-2016 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 <stdint.h>
#include <unistd.h>
#include <algorithm>
#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,
TEST_ID_END
};
bool read_stdin(std::vector<char> &data) {
char 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;
}
int do_fuzz()
{
std::vector<char> buffer;
if (!read_stdin(buffer)) return 0;
if (buffer.size() < sizeof(uint32_t)) return 0;
uint32_t test_id = 0xffffffff;
memcpy(&test_id, &buffer[0], 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
{
CCoins block;
ds >> block;
} 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;
}
default:
return 0;
}
return 0;
}
int main(int argc, char **argv)
{
ECCVerifyHandle globalVerifyHandle;
#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)) {
do_fuzz();
}
return 0;
#else
return do_fuzz();
#endif
}