// 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 #include #include #include 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 &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 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; } default: return 0; } return 0; } static std::unique_ptr globalVerifyHandle; void initialize() { globalVerifyHandle = std::unique_ptr(new ECCVerifyHandle()); } // This function is used by libFuzzer extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { test_one_input(std::vector(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 buffer; if (!read_stdin(buffer)) { continue; } ret = test_one_input(buffer); } return ret; #else std::vector buffer; if (!read_stdin(buffer)) { return 0; } return test_one_input(buffer); #endif }