Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
beea51f9c8 | ||
|
|
b3241958d9 | ||
|
|
8644b70b89 | ||
|
|
d335ad78c9 | ||
|
|
bc2bf34ed4 |
No files matched your search
@@ -42,7 +42,7 @@ jobs:
|
|||||||
# (native builds, no emulation), but buildx still needs a driver that
|
# (native builds, no emulation), but buildx still needs a driver that
|
||||||
# can assemble a multi-platform manifest list.
|
# can assemble a multi-platform manifest list.
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4
|
uses: docker/setup-buildx-action@594f3bf4285d9ea8dc53c9a0c9c4092420091003 # v4
|
||||||
|
|
||||||
- name: Log in to Gitea Container Registry
|
- name: Log in to Gitea Container Registry
|
||||||
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
|
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
name: Proto Fuzz Smoke
|
name: Fuzz Smoke
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -71,7 +71,7 @@ jobs:
|
|||||||
# regression; this is not meant to be exhaustive fuzzing.
|
# regression; this is not meant to be exhaustive fuzzing.
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
for target in decode_request decode_open_reply decode_echo_reply decode_params decode_varint; do
|
for target in decode_request decode_open_reply decode_echo_reply decode_params decode_varint server_core_datagrams; do
|
||||||
echo "::group::fuzz smoke: ${target}"
|
echo "::group::fuzz smoke: ${target}"
|
||||||
RUSTUP_TOOLCHAIN="${FUZZ_TOOLCHAIN}" cargo fuzz run --target "${FUZZ_TARGET}" "${target}" -- \
|
RUSTUP_TOOLCHAIN="${FUZZ_TOOLCHAIN}" cargo fuzz run --target "${FUZZ_TARGET}" "${target}" -- \
|
||||||
-max_total_time=10 \
|
-max_total_time=10 \
|
||||||
|
|||||||
Generated
+127
@@ -8,6 +8,18 @@ version = "1.4.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@@ -35,6 +47,12 @@ version = "1.0.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg_aliases"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cmov"
|
name = "cmov"
|
||||||
version = "0.5.4"
|
version = "0.5.4"
|
||||||
@@ -126,10 +144,24 @@ dependencies = [
|
|||||||
name = "irtt-proto-fuzz"
|
name = "irtt-proto-fuzz"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"arbitrary",
|
||||||
"irtt-proto",
|
"irtt-proto",
|
||||||
|
"irtt-server",
|
||||||
"libfuzzer-sys",
|
"libfuzzer-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "irtt-server"
|
||||||
|
version = "0.5.2"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"irtt-proto",
|
||||||
|
"nix",
|
||||||
|
"socket2",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jobserver"
|
name = "jobserver"
|
||||||
version = "0.1.35"
|
version = "0.1.35"
|
||||||
@@ -166,6 +198,45 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "1.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.31.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if",
|
||||||
|
"cfg_aliases",
|
||||||
|
"libc",
|
||||||
|
"memoffset",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.107"
|
version = "1.0.107"
|
||||||
@@ -196,6 +267,16 @@ version = "2.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "socket2"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
@@ -233,6 +314,31 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio"
|
||||||
|
version = "1.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"pin-project-lite",
|
||||||
|
"socket2",
|
||||||
|
"tokio-macros",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-macros"
|
||||||
|
version = "2.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.20.1"
|
version = "1.20.1"
|
||||||
@@ -244,3 +350,24 @@ name = "unicode-ident"
|
|||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.1+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-link"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.61.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
@@ -8,11 +8,15 @@ edition = "2021"
|
|||||||
cargo-fuzz = true
|
cargo-fuzz = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
arbitrary = "1.4.2"
|
||||||
libfuzzer-sys = "0.4.13"
|
libfuzzer-sys = "0.4.13"
|
||||||
|
|
||||||
[dependencies.irtt-proto]
|
[dependencies.irtt-proto]
|
||||||
path = "../crates/irtt-proto"
|
path = "../crates/irtt-proto"
|
||||||
|
|
||||||
|
[dependencies.irtt-server]
|
||||||
|
path = "../crates/irtt-server"
|
||||||
|
|
||||||
# Use independent workspace for fuzzers
|
# Use independent workspace for fuzzers
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["."]
|
members = ["."]
|
||||||
@@ -51,3 +55,10 @@ path = "fuzz_targets/decode_varint.rs"
|
|||||||
test = false
|
test = false
|
||||||
doc = false
|
doc = false
|
||||||
bench = false
|
bench = false
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "server_core_datagrams"
|
||||||
|
path = "fuzz_targets/server_core_datagrams.rs"
|
||||||
|
test = false
|
||||||
|
doc = false
|
||||||
|
bench = false
|
||||||
+9
-6
@@ -1,6 +1,7 @@
|
|||||||
# `irtt-proto` fuzzing
|
# `irtt-rs` fuzzing
|
||||||
|
|
||||||
Coverage-guided fuzzing of `irtt-proto`'s wire decoders via
|
Coverage-guided fuzzing of `irtt-proto` wire decoders and `irtt-server`'s public
|
||||||
|
`ServerCore::handle_datagram` API via
|
||||||
[`cargo-fuzz`](https://github.com/rust-fuzz/cargo-fuzz)/libFuzzer.
|
[`cargo-fuzz`](https://github.com/rust-fuzz/cargo-fuzz)/libFuzzer.
|
||||||
|
|
||||||
This project is intentionally isolated from the normal stable/MSRV
|
This project is intentionally isolated from the normal stable/MSRV
|
||||||
@@ -22,14 +23,16 @@ of the root workspace, requires nightly Rust, and is not built by
|
|||||||
| `decode_echo_reply` | `decode_echo_reply` against a deterministic, bounded `Params` matrix, unauthenticated and HMAC-authenticated |
|
| `decode_echo_reply` | `decode_echo_reply` against a deterministic, bounded `Params` matrix, unauthenticated and HMAC-authenticated |
|
||||||
| `decode_params` | `Params::decode` and `Params::decode_with_presence`, plus an encode/decode round trip |
|
| `decode_params` | `Params::decode` and `Params::decode_with_presence`, plus an encode/decode round trip |
|
||||||
| `decode_varint` | `varint::decode_uvarint`/`decode_varint` and their round trip through `encode_uvarint`/`encode_varint` |
|
| `decode_varint` | `varint::decode_uvarint`/`decode_varint` and their round trip through `encode_uvarint`/`encode_varint` |
|
||||||
|
| `server_core_datagrams` | A bounded mix of raw datagrams and production-encoded Open/Echo/Close requests against one `ServerCore`; it varies IPv4/IPv6 peers, session configuration, and bounded (up to 128-byte) HMAC keys, authenticates keyed requests, reuses issued tokens, and asserts the session cap |
|
||||||
|
|
||||||
The invariant every target asserts is: **arbitrary bytes must never panic**.
|
The invariant every target asserts is: **arbitrary bytes must never panic**.
|
||||||
Returning `Err` is normal and expected; a successful decode is also normal.
|
Returning `Err` is normal and expected; a successful decode is also normal.
|
||||||
|
|
||||||
Every target bounds its input to 128 KiB (`MAX_INPUT_LEN` in each harness) so
|
Every target bounds its input (`MAX_INPUT_LEN` in each harness) so libFuzzer
|
||||||
libFuzzer spends its time exploring protocol structure rather than
|
spends its time exploring protocol structure rather than allocating/copying
|
||||||
allocating/copying megabytes — production IRTT datagrams are UDP-sized, well
|
megabytes. `server_core_datagrams` additionally caps its sequence length and
|
||||||
under this bound.
|
each individual datagram and configures the core to the same packet cap, so one
|
||||||
|
libFuzzer input cannot become a tiny DoS benchmark.
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,186 @@
|
|||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use arbitrary::Unstructured;
|
||||||
|
use irtt_proto::{decode_open_reply, encode_request, Params, RequestToEncode};
|
||||||
|
use irtt_server::{ServerConfig, ServerCore};
|
||||||
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
|
/// Bounds one libFuzzer input as well as the work it can ask the core to do.
|
||||||
|
/// These are deliberately much smaller than a production UDP payload: the
|
||||||
|
/// target is stateful parser/session exploration, not packet-size throughput.
|
||||||
|
const MAX_INPUT_LEN: usize = 32 * 1024;
|
||||||
|
const MAX_DATAGRAMS: usize = 16;
|
||||||
|
const MAX_DATAGRAM_LEN: usize = 2 * 1024;
|
||||||
|
const MAX_SESSIONS: u8 = 8;
|
||||||
|
const MAX_HMAC_KEY_LEN: usize = 128;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct FuzzSession {
|
||||||
|
token: u64,
|
||||||
|
peer: SocketAddr,
|
||||||
|
params: Params,
|
||||||
|
}
|
||||||
|
|
||||||
|
fuzz_target!(|data: &[u8]| {
|
||||||
|
if data.len() > MAX_INPUT_LEN {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut input = Unstructured::new(data);
|
||||||
|
let Ok(mut config) = config(&mut input) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let hmac_key = match input.arbitrary::<bool>() {
|
||||||
|
Ok(true) => {
|
||||||
|
let Ok(length) = input.int_in_range(1..=MAX_HMAC_KEY_LEN) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
input.bytes(length).ok()
|
||||||
|
}
|
||||||
|
Ok(false) => None,
|
||||||
|
Err(_) => return,
|
||||||
|
};
|
||||||
|
if let Some(key) = hmac_key {
|
||||||
|
config = config.with_hmac_key(key);
|
||||||
|
}
|
||||||
|
let mut core = ServerCore::new(config);
|
||||||
|
let mut sessions = Vec::new();
|
||||||
|
|
||||||
|
for _ in 0..MAX_DATAGRAMS {
|
||||||
|
let Ok(operation) = input.arbitrary::<u8>() else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
match operation % 4 {
|
||||||
|
// Keep arbitrary-byte admission coverage alongside the stateful
|
||||||
|
// production-encoded requests below.
|
||||||
|
0 => raw_datagram(&mut core, &mut input),
|
||||||
|
1 => open_session(&mut core, &mut input, hmac_key, &mut sessions),
|
||||||
|
2 => echo_session(&mut core, &mut input, hmac_key, &sessions),
|
||||||
|
_ => close_session(&mut core, &mut input, hmac_key, &mut sessions),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arbitrary network input is expected to be rejected or to produce an
|
||||||
|
// internal error in exceptional host conditions. It must never panic,
|
||||||
|
// and it may never grow the bounded table past its configured cap.
|
||||||
|
assert!(core.session_count() <= core.config().max_sessions());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fn config(input: &mut Unstructured<'_>) -> arbitrary::Result<ServerConfig> {
|
||||||
|
let max_sessions = usize::from(input.int_in_range(0..=MAX_SESSIONS)?);
|
||||||
|
Ok(ServerConfig::default()
|
||||||
|
.with_max_sessions(max_sessions)
|
||||||
|
.with_max_packet_length(MAX_DATAGRAM_LEN)
|
||||||
|
.with_min_send_interval(Duration::ZERO))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn raw_datagram(core: &mut ServerCore, input: &mut Unstructured<'_>) {
|
||||||
|
let (Ok(peer), Ok(length)) = (peer(input), input.int_in_range(0..=MAX_DATAGRAM_LEN)) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Ok(packet) = input.bytes(length) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let _ = core.handle_datagram(peer, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn open_session(
|
||||||
|
core: &mut ServerCore,
|
||||||
|
input: &mut Unstructured<'_>,
|
||||||
|
hmac_key: Option<&[u8]>,
|
||||||
|
sessions: &mut Vec<FuzzSession>,
|
||||||
|
) {
|
||||||
|
let Ok(peer) = peer(input) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let params = session_params();
|
||||||
|
let request = encode_request(
|
||||||
|
RequestToEncode::Open {
|
||||||
|
params: ¶ms,
|
||||||
|
no_test: false,
|
||||||
|
},
|
||||||
|
hmac_key,
|
||||||
|
)
|
||||||
|
.expect("fixed valid fuzz open must encode");
|
||||||
|
let Ok(Some(reply)) = core.handle_datagram(peer, &request) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Ok(reply) = decode_open_reply(reply.bytes(), hmac_key) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
sessions.push(FuzzSession {
|
||||||
|
token: reply.token,
|
||||||
|
peer,
|
||||||
|
params: reply.params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn echo_session(
|
||||||
|
core: &mut ServerCore,
|
||||||
|
input: &mut Unstructured<'_>,
|
||||||
|
hmac_key: Option<&[u8]>,
|
||||||
|
sessions: &[FuzzSession],
|
||||||
|
) {
|
||||||
|
let Some(session) =
|
||||||
|
sessions.get(usize::from(input.arbitrary::<u8>().unwrap_or(0)) % sessions.len().max(1))
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let sequence = input.arbitrary().unwrap_or_default();
|
||||||
|
let request = encode_request(
|
||||||
|
RequestToEncode::Echo {
|
||||||
|
token: session.token,
|
||||||
|
sequence,
|
||||||
|
params: &session.params,
|
||||||
|
payload: &[],
|
||||||
|
},
|
||||||
|
hmac_key,
|
||||||
|
)
|
||||||
|
.expect("fixed valid fuzz echo must encode");
|
||||||
|
let _ = core.handle_datagram(session.peer, &request);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close_session(
|
||||||
|
core: &mut ServerCore,
|
||||||
|
input: &mut Unstructured<'_>,
|
||||||
|
hmac_key: Option<&[u8]>,
|
||||||
|
sessions: &mut Vec<FuzzSession>,
|
||||||
|
) {
|
||||||
|
let index = usize::from(input.arbitrary::<u8>().unwrap_or(0)) % sessions.len().max(1);
|
||||||
|
let Some(session) = sessions.get(index) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let request = encode_request(
|
||||||
|
RequestToEncode::Close {
|
||||||
|
token: session.token,
|
||||||
|
},
|
||||||
|
hmac_key,
|
||||||
|
)
|
||||||
|
.expect("fixed valid fuzz close must encode");
|
||||||
|
let _ = core.handle_datagram(session.peer, &request);
|
||||||
|
sessions.swap_remove(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn session_params() -> Params {
|
||||||
|
Params {
|
||||||
|
protocol_version: 1,
|
||||||
|
length: 256,
|
||||||
|
..Params::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peer(input: &mut Unstructured<'_>) -> arbitrary::Result<SocketAddr> {
|
||||||
|
let port = input.arbitrary()?;
|
||||||
|
let address = if input.arbitrary()? {
|
||||||
|
IpAddr::V4(Ipv4Addr::from(input.arbitrary::<[u8; 4]>()?))
|
||||||
|
} else {
|
||||||
|
IpAddr::V6(Ipv6Addr::from(input.arbitrary::<[u8; 16]>()?))
|
||||||
|
};
|
||||||
|
Ok(SocketAddr::new(address, port))
|
||||||
|
}
|
||||||
Reference in new issue
Block a user