You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
328 lines
8.3 KiB
328 lines
8.3 KiB
// 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 "blockencodings.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, |
|
BLOCKTRANSACTIONS_DESERIALIZE, |
|
BLOCKTRANSACTIONSREQUEST_DESERIALIZE, |
|
TEST_ID_END |
|
}; |
|
|
|
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; |
|
} |
|
|
|
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 |
|
}
|
|
|