LCOV - code coverage report
Current view: top level - src/ipc/test/fuzz - ipc.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 100.0 % 80 80
Test Date: 2026-08-01 06:30:48 Functions: 100.0 % 15 15
Branches: 52.4 % 126 66

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2026-present 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 <primitives/transaction.h>
       6                 :             : #include <capnp/capability.h>
       7                 :             : #include <capnp/rpc.h>
       8                 :             : #include <ipc/util.h>
       9                 :             : #include <kj/memory.h>
      10                 :             : #include <mp/proxy-io.h>
      11                 :             : #include <mp/proxy.h>
      12                 :             : #include <test/fuzz/FuzzedDataProvider.h>
      13                 :             : #include <test/fuzz/fuzz.h>
      14                 :             : #include <ipc/test/fuzz/ipc_fuzz.capnp.h>
      15                 :             : #include <ipc/test/fuzz/ipc_fuzz.capnp.proxy.h>
      16                 :             : #include <ipc/test/fuzz/ipc_fuzz.h>
      17                 :             : #include <test/fuzz/util.h>
      18                 :             : #include <test/util/setup_common.h>
      19                 :             : 
      20                 :             : #include <future>
      21                 :             : #include <memory>
      22                 :             : #include <stdexcept>
      23                 :             : #include <thread>
      24                 :             : 
      25                 :             : namespace {
      26                 :             : class IpcFuzzSetup
      27                 :             : {
      28                 :             : public:
      29                 :           1 :     IpcFuzzSetup()
      30         [ +  - ]:           1 :     {
      31         [ +  - ]:           1 :         std::promise<std::unique_ptr<mp::ProxyClient<test::fuzz::messages::IpcFuzzInterface>>> client_promise;
      32         [ +  - ]:           1 :         auto client_future{client_promise.get_future()};
      33                 :           1 :         m_loop_thread = std::thread([&client_promise] {
      34         [ +  - ]:           1 :             mp::EventLoop loop("ipc-fuzz", [](mp::LogMessage message) {
      35   [ -  +  -  - ]:        6123 :                 if (message.level == mp::Log::Raise) throw std::runtime_error(message.message);
      36         [ +  - ]:        6124 :             });
      37         [ +  - ]:           1 :             auto pipe = loop.m_io_context.provider->newTwoWayPipe();
      38                 :             : 
      39                 :           1 :             auto server_connection = std::make_unique<mp::Connection>(
      40                 :             :                 loop,
      41                 :             :                 kj::mv(pipe.ends[0]),
      42                 :           1 :                 [&](mp::Connection& connection) {
      43                 :           1 :                     auto server_proxy = kj::heap<mp::ProxyServer<test::fuzz::messages::IpcFuzzInterface>>(
      44         [ +  - ]:           1 :                         std::make_shared<IpcFuzzImplementation>(), connection);
      45   [ +  -  +  - ]:           1 :                     return capnp::Capability::Client(kj::mv(server_proxy));
      46         [ +  - ]:           2 :                 });
      47   [ +  -  +  - ]:           2 :             server_connection->onDisconnect([&] { server_connection.reset(); });
      48                 :             : 
      49         [ +  - ]:           1 :             auto client_connection = std::make_unique<mp::Connection>(loop, kj::mv(pipe.ends[1]));
      50                 :           1 :             auto client_proxy = std::make_unique<mp::ProxyClient<test::fuzz::messages::IpcFuzzInterface>>(
      51   [ +  -  +  -  :           1 :                 client_connection->m_rpc_system->bootstrap(mp::ServerVatId().vat_id)
                   +  - ]
      52         [ +  - ]:           1 :                     .castAs<test::fuzz::messages::IpcFuzzInterface>(),
      53         [ +  - ]:           1 :                 client_connection.get(),
      54   [ +  -  +  - ]:           2 :                 /* destroy_connection= */ true);
      55         [ +  - ]:           1 :             (void)client_connection.release();
      56                 :             : 
      57         [ +  - ]:           1 :             client_promise.set_value(std::move(client_proxy));
      58         [ +  - ]:           1 :             loop.loop();
      59   [ +  -  +  - ]:           2 :         });
      60   [ +  -  -  + ]:           1 :         m_client = client_future.get();
      61                 :           1 :     }
      62                 :             : 
      63                 :           1 :     ~IpcFuzzSetup()
      64                 :             :     {
      65         [ +  - ]:           1 :         m_client.reset();
      66         [ +  - ]:           1 :         if (m_loop_thread.joinable()) m_loop_thread.join();
      67                 :           1 :     }
      68                 :             : 
      69                 :             :     std::unique_ptr<mp::ProxyClient<test::fuzz::messages::IpcFuzzInterface>> m_client;
      70                 :             : 
      71                 :             : private:
      72                 :             :     std::thread m_loop_thread;
      73                 :             : };
      74                 :             : 
      75                 :             : static IpcFuzzSetup* g_ipc;
      76                 :             : 
      77                 :           1 : static void initialize_ipc()
      78                 :             : {
      79   [ +  -  +  -  :           1 :     static const auto testing_setup = MakeNoLogFileContext<>();
                   +  - ]
      80                 :           1 :     (void)testing_setup;
      81                 :             : 
      82                 :             :     // Ensure the thread's ThreadContext is created before the IPC setup, so
      83                 :             :     // it is destroyed after it, since C++ destroys thread_local objects in
      84                 :             :     // reverse construction order.
      85                 :           1 :     mp::CurrentThread();
      86                 :             : 
      87         [ +  - ]:           1 :     thread_local static IpcFuzzSetup ipc; // NOLINT(bitcoin-nontrivial-threadlocal)
      88                 :           1 :     g_ipc = &ipc;
      89                 :           1 : }
      90                 :             : 
      91         [ +  - ]:        1447 : FUZZ_TARGET(ipc, .init = initialize_ipc)
      92                 :             : {
      93                 :         973 :     auto& ipc = *g_ipc;
      94                 :         973 :     FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
      95   [ +  +  +  + ]:        1973 :     LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 64) {
      96                 :        1000 :         CallOneOf(
      97                 :             :             fuzzed_data_provider,
      98                 :          34 :             [&] {
      99                 :          34 :                 static constexpr int MIN_ADD{-1'000'000};
     100                 :          34 :                 static constexpr int MAX_ADD{1'000'000};
     101                 :          34 :                 const int a = fuzzed_data_provider.ConsumeIntegralInRange<int>(MIN_ADD, MAX_ADD);
     102                 :          34 :                 const int b = fuzzed_data_provider.ConsumeIntegralInRange<int>(MIN_ADD, MAX_ADD);
     103         [ -  + ]:          34 :                 assert(ipc.m_client->add(a, b) == a + b);
     104                 :          34 :             },
     105                 :         105 :             [&] {
     106                 :         105 :                 COutPoint outpoint{Txid::FromUint256(ConsumeUInt256(fuzzed_data_provider)),
     107                 :         105 :                                    fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
     108                 :         105 :                 COutPoint expected{outpoint.hash, outpoint.n ^ 0xFFFFFFFFu};
     109         [ -  + ]:         105 :                 assert(ipc.m_client->passOutPoint(outpoint) == expected);
     110                 :         105 :             },
     111                 :          43 :             [&] {
     112                 :          43 :                 std::vector<uint8_t> value = ConsumeRandomLengthByteVector<uint8_t>(fuzzed_data_provider, 512);
     113         [ +  - ]:          43 :                 std::vector<uint8_t> expected{value.rbegin(), value.rend()};
     114   [ +  -  +  -  :          86 :                 assert(ipc.m_client->passVectorUint8(value) == expected);
                   -  + ]
     115                 :          43 :             },
     116                 :         188 :             [&] {
     117                 :         188 :                 CScript script{ConsumeScript(fuzzed_data_provider)};
     118                 :         188 :                 CScript expected{script};
     119         [ +  - ]:         188 :                 expected << OP_NOP;
     120   [ +  -  -  + ]:         376 :                 assert(ipc.m_client->passScript(script) == expected);
     121                 :         188 :             },
     122                 :         163 :             [&] {
     123         [ +  - ]:         163 :                 UniValue value;
     124   [ +  -  +  -  :         326 :                 if (!value.read(fuzzed_data_provider.ConsumeRandomLengthString(512))) return;
                   +  + ]
     125   [ +  -  +  -  :          72 :                 assert(ipc.m_client->passUniValue(value).write() == value.write());
          +  -  +  -  -  
                      + ]
     126                 :         163 :             },
     127                 :         467 :             [&] {
     128                 :         467 :                 const CMutableTransaction mutable_tx = ConsumeTransaction(fuzzed_data_provider, std::nullopt);
     129         [ +  + ]:         467 :                 if (mutable_tx.vin.empty()) return;
     130         [ +  - ]:         358 :                 const CTransactionRef tx = MakeTransactionRef(mutable_tx);
     131   [ +  -  +  -  :        1432 :                 assert(*ipc.m_client->passTransaction(tx) == *tx);
          -  +  +  -  +  
                      - ]
     132                 :         825 :             });
     133                 :             :     }
     134                 :         973 : }
     135                 :             : } // namespace
        

Generated by: LCOV version