tests: Add fuzzing harness for CheckBlock(…) and other CBlock related functions #17071

pull practicalswift wants to merge 2 commits into bitcoin:master from practicalswift:fuzzers-block changing 3 files +71 −0
  1. practicalswift commented at 2:43 pm on October 7, 2019: contributor

    Add fuzzing harness for CheckBlock(...) and other CBlock related functions.

    Testing this PR

    Run:

    0$ CC=clang CXX=clang++ ./configure --enable-fuzz --with-sanitizers=address,fuzzer,undefined
    1$ make
    2$ src/test/fuzz/block
    3
    4# And to to quickly verify that the relevant code regions are triggered, that the
    5# fuzzing throughput seems reasonable, etc.
    6$ contrib/devtools/test_fuzzing_harnesses.sh '^block$'
    

    test_fuzzing_harnesses.sh can be found in PR #17000.

  2. in src/test/fuzz/fuzz.cpp:28 in 05d1ec551d outdated
    24@@ -25,6 +25,7 @@ static bool read_stdin(std::vector<uint8_t>& data)
    25 static void initialize()
    26 {
    27     const static auto verify_handle = MakeUnique<ECCVerifyHandle>();
    28+    SelectParams(CBaseChainParams::REGTEST);
    


    MarcoFalke commented at 2:49 pm on October 7, 2019:

    In commit 115bafe488ef0c53a88c2bc1e1b0508867c1daa8:

    Not sure if we want to pick regtest for all tests. I’d argue to pick main.

    Or maybe leave it to the individual tests to pick the params? This will result in a (slight) run time cost, but might make the code more clear?


    practicalswift commented at 3:39 pm on October 7, 2019:

    It not always entirely clear which functions that indirectly depend on params being selected and the requirement can be quite far down in the call graph.

    An example is from when I fuzzed EvalDescriptorStringOrObject:

    When using this harness the fuzzer managed to create the input string "addr()" after roughly three million executions. That input triggered the following assertion failure:

    0[#3170783](/bitcoin-bitcoin/3170783/)	REDUCE cov: 3338 ft: 7992 corp: 325/63Kb exec/s: 1258 rss: 272Mb L: 61/4090 MS: 2 ChangeASCIIInt-EraseBytes-
    1fuzzer: chainparams.cpp:385: const CChainParams &Params(): Assertion `globalChainParams' failed.
    2...
    3\"addr()\"
    

    Turns out EvalDescriptorStringOrObject calls Parse which calls DecodeDestination which in turn depends on params being selected.

    Since the requirement can run quite deep I think we should pick a network in the general initialize() so that harness writers don’t have to worry about crossing any code paths with params requirements that will generate faux crashes.

    OTOH, I don’t feel strongly about the particular choice of network - I just choose regtest since that seemed like the least adventurous choice :)

    What would be the pros/cons of going with main instead of going regtest (or test)?


    MarcoFalke commented at 3:49 pm on October 7, 2019:

    I’d rather want to test against a (clean-as-possible) mainnet, than a testnet. However, some tests might want to use segwit or lower difficulty blocks, which is enabled only on regtest from genesis.

    I think the choice really depends on each individual test.

    I see that you run into a particular issue with the chainparams, but similarly a fuzzer might find a code path that requires connman or a mempool, or anything else. In that case we’d have to initialize the full (Basic)Testingsetup here. Which in turn is not only expensive and wasteful to do, but also hard to reset for each input. So I’d reiterate my previous point that this should probably be picked for each test case either:

    • Nothing at all
    • A plain SelectParams
    • An advanced BasicTestingSetup
    • A full TestingSetup

    practicalswift commented at 3:58 pm on October 7, 2019:
    My fuzzing experience is that chainparams requirements are more scattered across the code base compared to connman and mempool requirements and thus more likely to trip on accidentally. Perhaps we can take the pick-level-of-initialization stuff in a follow-up PR?

    MarcoFalke commented at 4:04 pm on October 7, 2019:
    Let’s wait to see other people’s opinion on this

    practicalswift commented at 8:51 pm on October 16, 2019:

    Feedback addressed. Now allowing individual tests to pick the params.

    Picking regtest for this override. regtest feels like the least risky option in case of fuzzer gone haywire. Think about the theoretical scenario of a fuzzer say writing to disk for some strange reason. Also nice with low difficulty :)

    Please re-review.

  3. in src/test/fuzz/block.cpp:1 in 05d1ec551d outdated
    0@@ -0,0 +1,58 @@
    1+// Copyright (c) 2009-2019 The Bitcoin Core developers
    


    MarcoFalke commented at 2:49 pm on October 7, 2019:
    Just 2019? ;)
  4. in src/test/fuzz/block.cpp:38 in 05d1ec551d outdated
    33+        return;
    34+    }
    35+
    36+    const Consensus::Params& consensus_params = Params().GetConsensus();
    37+    CValidationState validation_state_pow_and_merkle;
    38+    const bool valid_incl_pow_and_merkle = CheckBlock(block, validation_state_pow_and_merkle, consensus_params, true, true);
    


    MarcoFalke commented at 2:50 pm on October 7, 2019:

    style-nit: Could use named arguments?

    0/* bla */ true, /* foo */ false
    
  5. MarcoFalke commented at 2:50 pm on October 7, 2019: member
    Concept ACK
  6. practicalswift force-pushed on Oct 7, 2019
  7. fanquake added the label Tests on Oct 7, 2019
  8. DrahtBot commented at 6:34 pm on October 7, 2019: member

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #17229 (tests: Add fuzzing harnesses for various Base{32,58,64} and hex related functions by practicalswift)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  9. practicalswift force-pushed on Oct 9, 2019
  10. DrahtBot added the label Needs rebase on Oct 10, 2019
  11. practicalswift force-pushed on Oct 10, 2019
  12. DrahtBot removed the label Needs rebase on Oct 10, 2019
  13. MarcoFalke added the label Waiting for author on Oct 12, 2019
  14. MarcoFalke removed the label Waiting for author on Oct 12, 2019
  15. practicalswift force-pushed on Oct 16, 2019
  16. DrahtBot added the label Needs rebase on Oct 24, 2019
  17. practicalswift force-pushed on Oct 24, 2019
  18. practicalswift commented at 9:28 pm on October 24, 2019: contributor
    Rebased! :)
  19. DrahtBot removed the label Needs rebase on Oct 24, 2019
  20. practicalswift force-pushed on Oct 31, 2019
  21. practicalswift commented at 2:14 pm on October 31, 2019: contributor
    Rebased and added a fuzzing harness for ContextualCheckBlock(…).
  22. practicalswift commented at 3:24 pm on October 31, 2019: contributor

    @MarcoFalke

    When fuzzing BlockWitnessMerkleRoot(…) I noticed that leaves[0].SetNull() is done also in the case when leaves.empty() (due to block.vtx.empty()):

    https://github.com/bitcoin/bitcoin/blob/d0f81a96d9c158a9226dc946bdd61d48c4d42959/src/consensus/merkle.cpp#L75-L84

    Makes sense to guard against this? :)

    Update: Working around this by simply skipping the call to BlockWitnessMerkleRoot(…) in case of block.vtx.empty().

  23. DrahtBot added the label Needs rebase on Nov 5, 2019
  24. practicalswift force-pushed on Nov 6, 2019
  25. DrahtBot removed the label Needs rebase on Nov 6, 2019
  26. practicalswift force-pushed on Dec 6, 2019
  27. practicalswift commented at 9:09 am on December 6, 2019: contributor
    Rebased! :)
  28. DrahtBot added the label Needs rebase on Dec 6, 2019
  29. DrahtBot removed the label Needs rebase on Dec 6, 2019
  30. practicalswift force-pushed on Dec 9, 2019
  31. practicalswift commented at 8:30 pm on December 9, 2019: contributor
    Rebased! :)
  32. in src/Makefile.test.include:233 in 96bae2b0fb outdated
    223@@ -224,11 +224,11 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
    224 endif
    225 
    226 if ENABLE_FUZZ
    227-test_fuzz_block_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
    228-test_fuzz_block_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_DESERIALIZE=1
    


    MarcoFalke commented at 8:42 pm on December 9, 2019:
    You removed the compilation of this target, but not the code. Maybe it is better to leave the target and compile it for now.

    practicalswift commented at 9:49 pm on December 9, 2019:
    Oh, good catch! Thanks! Now leaving the target instead.
  33. practicalswift force-pushed on Dec 9, 2019
  34. practicalswift commented at 9:35 pm on December 10, 2019: contributor
    Should be ready for final review :)
  35. in src/test/fuzz/block.cpp:20 in 1647af9218 outdated
    15+#include <version.h>
    16+
    17+#include <cassert>
    18+#include <string>
    19+
    20+bool ContextualCheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
    


    MarcoFalke commented at 6:17 pm on December 11, 2019:
    I’d prefer to put this in the header. Otherwise, the signature might get out of date with compiler annotations.

    practicalswift commented at 6:21 pm on December 11, 2019:
    Good point! I’ll fix.

    practicalswift commented at 11:04 pm on December 11, 2019:
    Fixed! Please re-review :)
  36. practicalswift force-pushed on Dec 11, 2019
  37. MarcoFalke commented at 5:01 pm on December 13, 2019: member
    ACK c5d08da5c38e4140f4b9465f3e8159bcd7874ab2
  38. in src/test/fuzz/block.cpp:44 in c5d08da5c3 outdated
    39     const Consensus::Params& consensus_params = Params().GetConsensus();
    40-    CValidationState validation_state_pow_and_merkle;
    41+
    42+    BlockValidationState validation_state_contextual;
    43+    const CBlockIndex* pindex_prev = nullptr;
    44+    (void)ContextualCheckBlock(block, validation_state_contextual, consensus_params, pindex_prev);
    


    MarcoFalke commented at 5:06 pm on December 13, 2019:

    in commit c5d08da5c38e4140f4b9465f3e8159bcd7874ab2:

    On a second thought I am not sure if it makes sense to expose this internal function for the sole purpose to pass a nullptr to it, which makes it execute pretty much no code paths anyway. Also, passing a nullptr never happens in reality.


    practicalswift commented at 11:39 pm on December 13, 2019:

    OK, reverted to previous version (see #17071 (review)).

    Please re-review :)


    MarcoFalke commented at 5:50 pm on December 15, 2019:
    I think there is a trade-off of unit and fuzz testing of internal functions that are not exposed in the header. In this particular instance pindex_prev is passed as a nullptr to ContextualCheckBlock, which then runs almost no code paths anyway. Not sure what the potential gains are of testing something that can never happen in reality.

    practicalswift commented at 9:41 pm on December 15, 2019:
    OK, dropped called to ContextualCheckBlock. Please re-review :)
  39. practicalswift force-pushed on Dec 13, 2019
  40. tests: Add corpora suppression (FUZZERS_MISSING_CORPORA) for fuzzers missing in https://github.com/bitcoin-core/qa-assets/tree/master/fuzz_seed_corpus ec8dcb0199
  41. practicalswift force-pushed on Dec 15, 2019
  42. tests: Add fuzzing harness for CheckBlock(...) and other CBlock related functions 893aa207e8
  43. practicalswift force-pushed on Dec 15, 2019
  44. MarcoFalke referenced this in commit 806a2c602c on Dec 16, 2019
  45. MarcoFalke merged this on Dec 16, 2019
  46. MarcoFalke closed this on Dec 16, 2019

  47. jasonbcox referenced this in commit e020b07987 on Oct 28, 2020
  48. practicalswift deleted the branch on Apr 10, 2021
  49. PastaPastaPasta referenced this in commit 0e25465e15 on Feb 26, 2022
  50. PastaPastaPasta referenced this in commit 1a628a596a on Feb 26, 2022
  51. kittywhiskers referenced this in commit 515c97906e on Feb 27, 2022
  52. kittywhiskers referenced this in commit 3a3ea44ed3 on Feb 27, 2022
  53. PastaPastaPasta referenced this in commit d254330372 on Feb 27, 2022
  54. kittywhiskers referenced this in commit a516063c95 on Feb 28, 2022
  55. kittywhiskers referenced this in commit 389e6a01ba on Feb 28, 2022
  56. kittywhiskers referenced this in commit 26085c4a8a on Feb 28, 2022
  57. PastaPastaPasta referenced this in commit d9ce5df395 on Mar 1, 2022
  58. PastaPastaPasta referenced this in commit b26851e7e2 on Mar 3, 2022
  59. PastaPastaPasta referenced this in commit 54684986a9 on Mar 3, 2022
  60. PastaPastaPasta referenced this in commit 36a5344f58 on Mar 5, 2022
  61. PastaPastaPasta referenced this in commit 0485b3a187 on Mar 7, 2022
  62. PastaPastaPasta referenced this in commit bf458b161c on Mar 29, 2022
  63. DrahtBot locked this on Aug 16, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-11-21 12:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me