New libFuzzer/AFL++ harnesses, each trapping on an oracle violation: p2p_json (nesting bound, round trip), p2p_connstr (endpoint round trip, pin idempotence, no silent re-pin), p2p_handshake (validators and the full acceptor bind the TLS peer), p2p_delta_stream (batch, session and bootstrap receive paths stay inside count and byte budgets), p2p_inbound (the manager inbound session through registry update) and topology_codec (decoded snapshots re-encode losslessly). p2p_delta now draws its exchange limits from the input. p2p_seeds.py writes framed-session seeds for FuzzedDataProvider layouts, dicts/p2p.dict carries the frame vocabulary, generate_corpus.sh accepts a local seedgen, and fuzz.sh no longer fails on macOS bash 3.2 when a target has no dictionary. The generated corpus stays untracked.
38 lines
1.5 KiB
C++
38 lines
1.5 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
// Copyright 2026 YAMS Contributors
|
|
|
|
// Direct-P2P delta/bootstrap control frames. The first bytes choose the exchange limits so the
|
|
// validators run against the same range of bounds a peer can negotiate, not only the defaults.
|
|
|
|
#include "../../src/daemon/p2p/p2p_fuzz.h"
|
|
|
|
// pi-lens-ignore: fatal error
|
|
#include <yams/daemon/p2p/p2p_delta.h>
|
|
#include <yams/daemon/p2p/p2p_transport.h>
|
|
|
|
#include <fuzzer/FuzzedDataProvider.h>
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <span>
|
|
#include <vector>
|
|
|
|
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size) {
|
|
using namespace yams::daemon::p2p;
|
|
if (data == nullptr || size > kP2pMaxControlFrameBytes + 64) {
|
|
return 0;
|
|
}
|
|
FuzzedDataProvider input(data, size);
|
|
DeltaExchangeOptions options;
|
|
options.maxDeltasPerBatch = input.ConsumeIntegralInRange<std::size_t>(0, 256);
|
|
options.maxBatches = input.ConsumeIntegralInRange<std::size_t>(0, 8192);
|
|
options.maxDeltasPerSession = input.ConsumeIntegralInRange<std::size_t>(0, 4096);
|
|
options.maxWireBytesPerSession = input.ConsumeIntegral<std::uint32_t>();
|
|
options.maxSnapshotRecords = input.ConsumeIntegralInRange<std::size_t>(0, 4096);
|
|
options.maxSnapshotWireBytes = input.ConsumeIntegral<std::uint32_t>();
|
|
const auto frame = input.ConsumeRemainingBytes<std::uint8_t>();
|
|
(void)detail::validateDeltaControlFrame(
|
|
std::span<const std::byte>(reinterpret_cast<const std::byte*>(frame.data()), frame.size()),
|
|
options);
|
|
return 0;
|
|
}
|