fuzz: improve ipc fuzz coverage #35916

pull enirox001 wants to merge 4 commits into bitcoin:master from enirox001:08-26-fuzz-ipc-coverage changing 3 files +292 −13
  1. enirox001 commented at 1:16 PM on August 6, 2026: contributor

    This PR follows up on #35118 and continues the IPC fuzzing work proposed in #23015.

    The initial ipc fuzz target exercised normal calls through a libmultiprocess client and server. This PR extends the target with

    • Server side assertions that verify arguments arrive unchanged (https://github.com/bitcoin/bitcoin/pull/35118#issuecomment-4452992198 and #35118#pullrequestreview-4539477599)
    • A callback call that exercises ipc communication in both directions.
    • Raw capnp requests containing arbitrary transaction and UniValue payloads, which are deserialized by a normal libmultiprocess server.
    • Raw capnp responses containing arbitrary transaction and UniValue payloads, which are deserialized by a normal libmultiprocess client.

    The raw request and response cases allow the fuzz target to exercise deserialization with data that was not first produced by libmultiprocess serialization.

    The ipc setup and callback handling closely follow the existing libmultiprocess tests, particularly their use of EventLoop, ProxyClient, ProxyServer, two-way pipes, and initThreadMap.

    The transaction and UniValue payload cases exercise the serialization hooks defined in common-types.h.

    These files may provide useful background when reviewing the changes.

    Generated coverage report after fuzzing the IPC target for a while using the qa-assets corpus.

  2. DrahtBot added the label Fuzzing on Aug 6, 2026
  3. DrahtBot commented at 1:16 PM on August 6, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/35916.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    Stale ACK jeanpablojp

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    No conflicts as of last run.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  4. enirox001 renamed this:
    fuzz: improve IPC fuzz coverage
    fuzz: improve ipc fuzz coverage
    on Aug 6, 2026
  5. jeanpablojp commented at 3:40 PM on August 15, 2026: contributor

    tACK bd24122dfbfbaded49ef551c01184b4b5b48e27f

    All green, and it matches the follow-up #35118 asked for.

  6. in src/ipc/test/fuzz/ipc.cpp:180 in bd24122dfb outdated
     175 | +            m_client->m_context.loop->m_task_set->add(request.send().then(
     176 | +                [&](auto&&) {
     177 | +                    done.set_value();
     178 | +                },
     179 | +                [&](kj::Exception&& exception) {
     180 | +                    done.set_exception(std::make_exception_ptr(
    


    jeanpablojp commented at 3:40 PM on August 15, 2026:

    Took me a bit to see why sendTransactionPayload swallows FAILED while sendUniValuePayload treats any kj error as fatal. That's correct, but you only get it by reading the hooks. A one-line comment would have helped, feel free to ignore.

                        // UniValue deserialization never throws (read() failure is ignored), so any kj error is unexpected.
                        done.set_exception(std::make_exception_ptr(
    

    enirox001 commented at 11:33 AM on August 26, 2026:

    Yes, I agree that this can be clarified a bit more, added the suggested comment to clarify why any KJ error is unexpected here. Thanks

  7. enirox001 force-pushed on Aug 26, 2026
  8. enirox001 force-pushed on Aug 26, 2026
  9. DrahtBot added the label CI failed on Aug 26, 2026
  10. DrahtBot commented at 12:34 PM on August 26, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task Windows native, fuzz, VS: https://github.com/bitcoin/bitcoin/actions/runs/32963804197/job/98161775031</sub> <sub>LLM reason (✨ experimental): CI failed because the fuzz target rpc crashed with Windows exit code 3221225477 (access violation).</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  11. DrahtBot removed the label CI failed on Aug 26, 2026
  12. enirox001 commented at 7:57 AM on August 28, 2026: contributor

    See the generated coverage report after fuzzing the IPC target for a while using the qa-assets corpus.

    Also included in the pr description

  13. DrahtBot added the label Needs rebase on Sep 14, 2026
  14. fuzz: assert IPC arguments on server side
    Keep a reference to the IPC fuzz implementation so fuzz inputs can be compared
    directly with values deserialized by the proxy server.
    
    This ensures serialization errors are detected on the client to server path instead
    of potentially being hidden by the return trip.
    d650d09a02
  15. fuzz: exercise IPC callback
    Add a callback interface to the IPC fuzz target so requests exercise communication
    from the server back to the client.
    
    Check the callback argument and return value on both sides.
    c74757bed3
  16. enirox001 force-pushed on Sep 14, 2026
  17. DrahtBot added the label CI failed on Sep 14, 2026
  18. DrahtBot commented at 10:24 AM on September 14, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task macOS native, fuzz: https://github.com/bitcoin/bitcoin/actions/runs/34830127159/job/103931261872</sub> <sub>LLM reason (✨ experimental): CI failed because the fuzz test (fuzz target ipc) crashed with std::runtime_error: invalid JSON received over IPC (uncaught exception, exit code 1).</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  19. enirox001 force-pushed on Sep 14, 2026
  20. DrahtBot removed the label Needs rebase on Sep 14, 2026
  21. DrahtBot removed the label CI failed on Sep 14, 2026
  22. in src/ipc/test/fuzz/ipc.cpp:322 in 1ea3507869 outdated
     316 | @@ -234,6 +317,12 @@ FUZZ_TARGET(ipc, .init = initialize_ipc)
     317 |              [&] {
     318 |                  ipc.sendUniValuePayload(
     319 |                      fuzzed_data_provider.ConsumeRandomLengthString(512));
     320 | +            },
     321 | +            [&] {
     322 | +                ipc.receiveTransactionPayload(ConsumeRandomLengthByteVector<uint8_t>(fuzzed_data_provider, 512));
    


    Eunovo commented at 9:34 AM on September 15, 2026:

    https://github.com/bitcoin/bitcoin/pull/35916/commits/1ea3507869869a93c136714d841fa5dd8788e8e0:

    Use ConsumeTransaction in src/test/fuzz/util.cpp to create a random tx from a FuzzedDataProvider instead of using a random lenght byte vector.


    enirox001 commented at 3:57 PM on September 16, 2026:

    We intentionally return arbitrary transaction bytes from the raw server so the client deserialization is exercised with malformed responses.

    Using ConsumeTransaction would only generate valid transactions and duplicate the existing passTransaction coverage.

    I’ve added a comment clarifying the purpose of this branch.

  23. in src/ipc/test/fuzz/ipc.cpp:325 in 1ea3507869 outdated
     316 | @@ -234,6 +317,12 @@ FUZZ_TARGET(ipc, .init = initialize_ipc)
     317 |              [&] {
     318 |                  ipc.sendUniValuePayload(
     319 |                      fuzzed_data_provider.ConsumeRandomLengthString(512));
     320 | +            },
     321 | +            [&] {
     322 | +                ipc.receiveTransactionPayload(ConsumeRandomLengthByteVector<uint8_t>(fuzzed_data_provider, 512));
     323 | +            },
     324 | +            [&] {
     325 | +                ipc.receiveUniValuePayload(fuzzed_data_provider.ConsumeRandomLengthString(512));
    


    Eunovo commented at 9:40 AM on September 15, 2026:

    https://github.com/bitcoin/bitcoin/pull/35916/commits/1ea3507869869a93c136714d841fa5dd8788e8e0:

    Most of the generated data will be invalid JSON; this means the fuzzer will hit the "invalid JSON received over IPC" error most of the time. I think it's much better to construct a valid JSON payload, the same way we construct valid TXs with ConsumeTransaction.


    enirox001 commented at 3:57 PM on September 16, 2026:

    Invalid json is intentional here because it tests client side rejection of malformed ipc responses.

    Valid json round trips are covered separately by passUniValue, which parses arbitrary input and proceeds when it is valid.

    I’ve added a comment clarifying the distinction.

  24. in src/ipc/test/fuzz/ipc.cpp:232 in f5db59400b outdated
     225 | @@ -166,6 +226,14 @@ FUZZ_TARGET(ipc, .init = initialize_ipc)
     226 |  
     227 |                  FuzzCallback callback{arg, result};
     228 |                  assert(ipc.m_client->callCallback(callback, arg) == result);
     229 | +            },
     230 | +            [&] {
     231 | +                ipc.sendTransactionPayload(
     232 | +                    ConsumeRandomLengthByteVector<uint8_t>(fuzzed_data_provider, 512));
    


    Eunovo commented at 9:53 AM on September 15, 2026:

    https://github.com/bitcoin/bitcoin/pull/35916/commits/f5db59400b7838beffef3cba34d6fbcf5df9a00c:

    You should use ConsumeTransaction from src/test/fuzz/util.cpp. Most of the vectors produced will be invalid.


    enirox001 commented at 3:59 PM on September 16, 2026:

    Same rationale as #35916 (review): this intentionally bypasses normal serialization to exercise malformed transaction payload handling.

  25. in src/ipc/test/fuzz/ipc.cpp:235 in f5db59400b outdated
     230 | +            [&] {
     231 | +                ipc.sendTransactionPayload(
     232 | +                    ConsumeRandomLengthByteVector<uint8_t>(fuzzed_data_provider, 512));
     233 | +            },
     234 | +            [&] {
     235 | +                ipc.sendUniValuePayload(
    


    Eunovo commented at 9:53 AM on September 15, 2026:

    enirox001 commented at 4:01 PM on September 16, 2026:

    Same reason as #35916 (review)

  26. Eunovo commented at 9:57 AM on September 15, 2026: contributor

    https://github.com/bitcoin/bitcoin/pull/35916/commits/1ea3507869869a93c136714d841fa5dd8788e8e0:

    I'm not sure why random bytes are being used for CTransaction and UniValue; the chances of a randomly generated byte vector deserialising to a CTransaction are slim.

  27. fuzz: send malformed IPC request payloads
    Use the underlying capnp client to send arbitrary transaction data and JSON text to the
    libmultiprocess server.
    
    Accept normal transaction deserialization failures while surfacing unexpected IPC errors.
    59cd6e3ff7
  28. fuzz: return malformed IPC response payloads
    Connect a normal libmultiprocess client to a manual capnp server.
    
    Return arbitrary transaction data and json text to exercise client side
    deserialization.
    84e54a419e
  29. enirox001 force-pushed on Sep 16, 2026

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-09-20 20:52 UTC

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