diff options
Diffstat (limited to 'fuzz/fuzz_tcp_reassembly.cpp')
| -rw-r--r-- | fuzz/fuzz_tcp_reassembly.cpp | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/fuzz/fuzz_tcp_reassembly.cpp b/fuzz/fuzz_tcp_reassembly.cpp new file mode 100644 index 0000000..78ca91c --- /dev/null +++ b/fuzz/fuzz_tcp_reassembly.cpp @@ -0,0 +1,42 @@ +#include <cstddef> +#include <cstdint> + +#include "wireframe/net/tcp_reassembly.hpp" + +using namespace wireframe::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<std::uint16_t>(data[pos + 8] << 8 | data[pos + 9]); + std::uint16_t dst_port = static_cast<std::uint16_t>(data[pos + 10] << 8 | data[pos + 11]); + std::uint32_t seq = static_cast<std::uint32_t>(data[pos + 12]) << 24 | + static_cast<std::uint32_t>(data[pos + 13]) << 16 | + static_cast<std::uint32_t>(data[pos + 14]) << 8 | data[pos + 15]; + std::uint8_t flags = data[pos + 16]; + std::uint16_t payload_len = + static_cast<std::uint16_t>(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<const unsigned char> payload{data + pos, take}; + pos += take; + + reassembler.process_segment(src, src_port, dst, dst_port, seq, flags, payload); + } + return 0; +} |