#include #include #include "packeteer/net/tcp_reassembly.hpp" using namespace packeteer::net; // Unlike the other fuzz harnesses, this drives *one* TcpReassembler // with a whole sequence of segments parsed out of a single input -- // the interesting bugs here are in cross-call state (the flow map, // per-direction sequence tracking, the buffer-size cap), not in // decoding one segment alone. Each record is a fixed 19-byte header // (src ip/port, dst ip/port, seq, flags, a payload length) followed by // that many payload bytes; malformed/truncated trailing records are // simply skipped rather than treated as an error, same as any other // best-effort parse in this project. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { TcpReassembler reassembler; size_t pos = 0; while (pos + 19 <= size) { Ipv4Address src{{data[pos], data[pos + 1], data[pos + 2], data[pos + 3]}}; Ipv4Address dst{{data[pos + 4], data[pos + 5], data[pos + 6], data[pos + 7]}}; std::uint16_t src_port = static_cast(data[pos + 8] << 8 | data[pos + 9]); std::uint16_t dst_port = static_cast(data[pos + 10] << 8 | data[pos + 11]); std::uint32_t seq = static_cast(data[pos + 12]) << 24 | static_cast(data[pos + 13]) << 16 | static_cast(data[pos + 14]) << 8 | data[pos + 15]; std::uint8_t flags = data[pos + 16]; std::uint16_t payload_len = static_cast(data[pos + 17] << 8 | data[pos + 18]); pos += 19; std::size_t available = size - pos; std::size_t take = payload_len < available ? payload_len : available; std::span payload{data + pos, take}; pos += take; reassembler.process_segment(src, src_port, dst, dst_port, seq, flags, payload); } return 0; }