fuzz: Add RPC interface fuzzing. Increase fuzzing coverage from 65% to 70%. #21169

pull practicalswift wants to merge 1 commits into bitcoin:master from practicalswift:fuzzing-rpc changing 2 files +379 −0
  1. practicalswift commented at 8:11 AM on February 13, 2021: contributor

    Add RPC interface fuzzing.

    This PR increases overall fuzzing line coverage from ~65% to ~70% 🎉

    To test this PR:

    $ make distclean
    $ ./autogen.sh
    $ CC=clang CXX=clang++ ./configure --enable-fuzz --with-sanitizers=address,fuzzer,undefined
    $ make -C src/ test/fuzz/fuzz
    $ FUZZ=rpc src/test/fuzz/fuzz
    

    See doc/fuzzing.md for more information on how to fuzz Bitcoin Core. Don't forget to contribute any coverage increasing inputs you find to the Bitcoin Core fuzzing corpus repo.

    Happy fuzzing :)

  2. fanquake added the label Tests on Feb 13, 2021
  3. practicalswift force-pushed on Feb 13, 2021
  4. in src/test/fuzz/rpc.cpp:47 in e4e3b56d30 outdated
      42 | +struct RPCFuzzTestingSetup : public TestingSetup {
      43 | +    RPCFuzzTestingSetup(const std::string& chain_name, const std::vector<const char*>& extra_args) : TestingSetup{chain_name, extra_args}
      44 | +    {
      45 | +    }
      46 | +
      47 | +    UniValue CallRPC(const std::string rpc_method, const std::vector<std::string>& arguments)
    


    jonatack commented at 2:52 PM on February 13, 2021:
        UniValue CallRPC(const std::string& rpc_method, const std::vector<std::string>& arguments)
    

    jonatack commented at 8:10 PM on February 15, 2021:

    First code review LGTM otherwise.


    practicalswift commented at 9:17 PM on April 27, 2021:

    Addressed!

  5. jonatack commented at 3:18 PM on February 13, 2021: member

    Concept ACK, debug build clean and it runs

    $ FUZZ=rpc src/test/fuzz/fuzz
    INFO: Seed: 974835892
    INFO: Loaded 1 modules   (625697 inline 8-bit counters): 625697 [0x5636dc7b9268, 0x5636dc851e89), 
    INFO: Loaded 1 PC tables (625697 PCs): 625697 [0x5636dc851e90,0x5636dd1de0a0), 
    INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
    INFO: A corpus is not provided, starting from an empty corpus
    [#2](/bitcoin-bitcoin/2/)	INITED cov: 110 ft: 111 corp: 1/1b exec/s: 0 rss: 191Mb
    [#4](/bitcoin-bitcoin/4/)	NEW    cov: 110 ft: 118 corp: 2/3b lim: 4 exec/s: 0 rss: 191Mb L: 2/2 MS: 2 ChangeBit-InsertByte-
    [#10](/bitcoin-bitcoin/10/)	NEW    cov: 110 ft: 125 corp: 3/6b lim: 4 exec/s: 0 rss: 191Mb L: 3/3 MS: 1 CopyPart-
    [#13](/bitcoin-bitcoin/13/)	NEW    cov: 110 ft: 130 corp: 4/10b lim: 4 exec/s: 0 rss: 191Mb L: 4/4 MS: 3 ChangeBinInt-EraseBytes-CrossOver-
    ...
    [#217864](/bitcoin-bitcoin/217864/)	REDUCE cov: 16595 ft: 45707 corp: 992/59Kb lim: 116 exec/s: 1998 rss: 616Mb L: 84/116 MS: 1 EraseBytes-
    [#218080](/bitcoin-bitcoin/218080/)	REDUCE cov: 16595 ft: 45709 corp: 993/59Kb lim: 116 exec/s: 2000 rss: 616Mb L: 115/116 MS: 1 InsertRepeatedBytes-
    [#218133](/bitcoin-bitcoin/218133/)	REDUCE cov: 16595 ft: 45709 corp: 993/59Kb lim: 116 exec/s: 2001 rss: 616Mb L: 84/116 MS: 3 ChangeByte-CMP-EraseBytes- DE: "St9exception"-
    	NEW_FUNC[1/25]: 0x5636d8897d20 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr_base.h:152
    	NEW_FUNC[2/25]: 0x5636d88db840 in std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<CBlock, std::allocator<CBlock>, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<CBlock, std::allocator<CBlock>, (__gnu_cxx::_Lock_policy)2> > >(std::allocator<std::_Sp_counted_ptr_inplace<CBlock, std::allocator<CBlock>, (__gnu_cxx::_Lock_policy)2> >&) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/allocated_ptr.h:96
    [#218742](/bitcoin-bitcoin/218742/)	REDUCE cov: 16767 ft: 45872 corp: 994/59Kb lim: 122 exec/s: 1988 rss: 616Mb L: 30/116 MS: 4 EraseBytes-ChangeBit-ChangeBinInt-CMP- DE: "submitblock"-
    
  6. in src/test/fuzz/rpc.cpp:318 in e4e3b56d30 outdated
     313 | +    return fuzzed_data_provider.ConsumeBool() ? ConsumeScalarRPCArgument(fuzzed_data_provider) : ConsumeArrayRPCArgument(fuzzed_data_provider);
     314 | +}
     315 | +
     316 | +RPCFuzzTestingSetup* InitializeRPCFuzzTestingSetup()
     317 | +{
     318 | +    static std::unique_ptr<RPCFuzzTestingSetup> setup = std::make_unique<RPCFuzzTestingSetup>(CBaseChainParams::REGTEST, std::vector<const char*>{"-nodebuglogfile"});
    


    MarcoFalke commented at 7:47 AM on February 22, 2021:

    Should use MakeNoLogFileContext?


    practicalswift commented at 9:09 PM on April 27, 2021:

    Good point! Done!

  7. MarcoFalke commented at 7:49 AM on February 22, 2021: member

    I am not sure if this is worth it. This needs a lot of maintenance (adding or removing rpcs, marking them unsafe, ...) and I am sceptical that this will find any actual issues.

  8. adamjonas commented at 4:35 PM on April 27, 2021: member

    @MarcoFalke to clarify, are you a NACK on this?

  9. practicalswift commented at 7:42 PM on April 27, 2021: contributor

    @adamjonas

    Good question and thanks for asking it explicitly! :)

    I should probably have stated that more clearly in the PR description, but it should be noted that this fuzzing harness is by far is the "most covering" harness in the repo.

    Including this harness in the existing set of fuzzing harnesses adds coverage to five(!) percent of the code base that is currently uncovered by fuzz testing. The total fuzzing coverage increases from 65% to 70%.

    The opportunities to achieve such extreme coverage jumps from adding a single harness are extremely rare at the relatively high levels of fuzzing coverage we've reached. TBH it would feel a bit disappointing if we had to pass on the excellent coverage opportunity that RPC fuzzing brings :) @MarcoFalke, if we can find a way to reduce/mitigate the potential maintenance work you predict in #21169 (comment) would you be willing to reconsider your position? :)

  10. practicalswift force-pushed on Apr 27, 2021
  11. in src/test/fuzz/rpc.cpp:72 in 555556e2fe outdated
      67 | +const std::vector<std::string> RPC_COMMANDS_NOT_SAFE_FOR_FUZZING{
      68 | +    "addconnection",        // avoid DNS lookups
      69 | +    "addnode",              // avoid DNS lookups
      70 | +    "addpeeraddress",       // avoid DNS lookups
      71 | +    "analyzepsbt",          // avoid signed integer overflow in CFeeRate::GetFee(unsigned long) (https://github.com/bitcoin/bitcoin/issues/20607)
      72 | +    "decoderawtransaction", // avoid signed integer overflow in ValueFromAmount(long const&) (https://github.com/bitcoin/bitcoin/pull/20406)
    


    MarcoFalke commented at 5:49 AM on April 28, 2021:

    fixed?


    practicalswift commented at 6:39 AM on April 28, 2021:

    Fixed! Thanks!

  12. in src/test/fuzz/rpc.cpp:353 in 555556e2fe outdated
     348 | +        if (!supported_rpc_command) {
     349 | +            std::cerr << "Error: Unknown RPC command \"" << rpc_command << "\" found in RPC_COMMANDS_NOT_SAFE_FOR_FUZZING. Please update " << __FILE__ << ".\n";
     350 | +            std::terminate();
     351 | +        }
     352 | +    }
     353 | +    const char* limit_to_rpc_command_env = getenv("LIMIT_TO_RPC_COMMAND");
    


    MarcoFalke commented at 5:57 AM on April 28, 2021:
        const char* limit_to_rpc_command_env = std::getenv("LIMIT_TO_RPC_COMMAND");
    

    practicalswift commented at 6:39 AM on April 28, 2021:

    Addressed. Thanks!

  13. in src/test/fuzz/rpc.cpp:62 in 555556e2fe outdated
      57 | +        return tableRPC.listCommands();
      58 | +    }
      59 | +};
      60 | +
      61 | +RPCFuzzTestingSetup* rpc_testing_setup = nullptr;
      62 | +std::string limit_to_rpc_command;
    


    MarcoFalke commented at 5:59 AM on April 28, 2021:
    std::string g_limit_to_rpc_command;
    

    practicalswift commented at 6:39 AM on April 28, 2021:

    Addressed. Thanks!

  14. fuzz: Add RPC interface fuzzing. Increase fuzzing coverage from 65% to 70%. 545404e7e1
  15. in src/test/fuzz/rpc.cpp:83 in 555556e2fe outdated
      78 | +    "generatetoaddress", // avoid timeout
      79 | +    "gettxoutproof",     // avoid slow execution
      80 | +#ifdef ENABLE_WALLET
      81 | +    "importwallet", // avoid reading from disk
      82 | +#endif
      83 | +    "invalidateblock", // avoid nullptr dereference in CBlockIndexWorkComparator::operator() (https://github.com/bitcoin/bitcoin/issues/20914)
    


    MarcoFalke commented at 6:02 AM on April 28, 2021:

    fixed


    practicalswift commented at 6:39 AM on April 28, 2021:

    Fixed! Thanks!

  16. practicalswift force-pushed on Apr 28, 2021
  17. MarcoFalke commented at 7:45 AM on April 28, 2021: member

    Concept ACK 545404e7e1c72985557ccffe865cea269143e5dd

    If this is leading to too much (maintenance) hassle, it can be reverted.

  18. MarcoFalke merged this on Apr 28, 2021
  19. MarcoFalke closed this on Apr 28, 2021

  20. in src/test/fuzz/rpc.cpp:77 in 545404e7e1
      72 | +    "dumptxoutset",   // avoid writing to disk
      73 | +#ifdef ENABLE_WALLET
      74 | +    "dumpwallet", // avoid writing to disk
      75 | +#endif
      76 | +    "echoipc",           // avoid assertion failure (Assertion `"EnsureAnyNodeContext(request.context).init" && check' failed.)
      77 | +    "generatetoaddress", // avoid timeout
    


    MarcoFalke commented at 8:10 AM on April 28, 2021:

    why is this unsafe, but the other generate* calls are safe?


    practicalswift commented at 6:48 PM on April 29, 2021:

    Thanks! Addressed in #21810:

        "generatetoaddress",    // avoid prohibitively slow execution (when `num_blocks` is large)
        "generatetodescriptor", // avoid prohibitively slow execution (when `nblocks` is large)
    
  21. in src/test/fuzz/rpc.cpp:6 in 545404e7e1
       0 | @@ -0,0 +1,378 @@
       1 | +// Copyright (c) 2021 The Bitcoin Core developers
       2 | +// Distributed under the MIT software license, see the accompanying
       3 | +// file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4 | +
       5 | +#include <base58.h>
       6 | +#include <chainparamsbase.h>
    


    MarcoFalke commented at 8:10 AM on April 28, 2021:

    unused?


    practicalswift commented at 7:05 PM on April 29, 2021:

    Thanks! Addressed in follow-up.

  22. in src/test/fuzz/rpc.cpp:8 in 545404e7e1
       0 | @@ -0,0 +1,378 @@
       1 | +// Copyright (c) 2021 The Bitcoin Core developers
       2 | +// Distributed under the MIT software license, see the accompanying
       3 | +// file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4 | +
       5 | +#include <base58.h>
       6 | +#include <chainparamsbase.h>
       7 | +#include <core_io.h>
       8 | +#include <interfaces/chain.h>
    


    MarcoFalke commented at 8:10 AM on April 28, 2021:

    unused?


    practicalswift commented at 7:05 PM on April 29, 2021:

    Thanks! Addressed in follow-up.

  23. in src/test/fuzz/rpc.cpp:83 in 545404e7e1
      78 | +    "gettxoutproof",     // avoid slow execution
      79 | +#ifdef ENABLE_WALLET
      80 | +    "importwallet", // avoid reading from disk
      81 | +    "loadwallet",   // avoid reading from disk
      82 | +#endif
      83 | +    "mockscheduler",         // avoid assertion failure (Assertion `delta_seconds.count() > 0 && delta_seconds < std::chrono::hours{1}' failed.)
    


    MarcoFalke commented at 8:10 AM on April 28, 2021:

    fixed?


    practicalswift commented at 7:05 PM on April 29, 2021:

    Seems so! Thanks! Re-enabled in follow-up.

  24. in src/test/fuzz/rpc.cpp:152 in 545404e7e1
     147 | +    "logging",
     148 | +    "ping",
     149 | +    "preciousblock",
     150 | +    "pruneblockchain",
     151 | +    "reconsiderblock",
     152 | +    "savemempool",
    


    MarcoFalke commented at 8:19 AM on April 28, 2021:

    This seems dangerous. If the rpc is ever changed to take a file path, how would we know to adjust this line?


    practicalswift commented at 6:56 PM on April 29, 2021:

    Good point. Disabled as a precautionary measure in #21810.

    dump*, save*, import* and load* commands should probably not be part of RPC_COMMANDS_SAFE_FOR_FUZZING.

    Longer term we could perhaps also find a clever way to annotate/auto-detect RPC commands with file path arguments and have them automatically removed from RPC_COMMANDS_SAFE_FOR_FUZZING if they are incorrectly included there for some reason. Belts and suspenders! :)

  25. sidhujag referenced this in commit 6c43015a68 on Apr 28, 2021
  26. MarcoFalke referenced this in commit ea71726a54 on May 3, 2021
  27. sidhujag referenced this in commit 3f760df98f on May 3, 2021
  28. gwillen referenced this in commit d51f42534f on Jun 1, 2022
  29. 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: 2026-04-16 15:14 UTC

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