From 1f167071fbe11f3b45a32f46cf3bfdf7c69d8ea8 Mon Sep 17 00:00:00 2001 From: Nils Andreas Svee Date: Thu, 7 May 2026 20:58:49 +0700 Subject: [PATCH] fix(client): reject invalid negotiated packet length --- .../src/client/tests/negotiation.rs | 24 +++++++++++++++++++ crates/irtt-client/src/session.rs | 5 ++++ 2 files changed, 29 insertions(+) diff --git a/crates/irtt-client/src/client/tests/negotiation.rs b/crates/irtt-client/src/client/tests/negotiation.rs index ef0525f..3870bc7 100644 --- a/crates/irtt-client/src/client/tests/negotiation.rs +++ b/crates/irtt-client/src/client/tests/negotiation.rs @@ -28,3 +28,27 @@ fn loose_negotiation_accepts_server_restricted_params() { returned.length = 0; assert!(validate_negotiated_params(&requested, &returned, NegotiationPolicy::Loose).is_ok()); } + +#[test] +fn loose_negotiation_rejects_negative_returned_length() { + let config = ClientConfig::default(); + let requested = params_from_config(&config).unwrap(); + let mut returned = requested.clone(); + returned.length = -1; + assert!(matches!( + validate_negotiated_params(&requested, &returned, NegotiationPolicy::Loose), + Err(ClientError::NegotiationRejected { reason }) if reason == "length must be non-negative" + )); +} + +#[test] +fn strict_negotiation_rejects_negative_returned_length() { + let config = ClientConfig::default(); + let requested = params_from_config(&config).unwrap(); + let mut returned = requested.clone(); + returned.length = -1; + assert!(matches!( + validate_negotiated_params(&requested, &returned, NegotiationPolicy::Strict), + Err(ClientError::NegotiationRejected { reason }) if reason == "length must be non-negative" + )); +} diff --git a/crates/irtt-client/src/session.rs b/crates/irtt-client/src/session.rs index 0988f06..9f928a8 100644 --- a/crates/irtt-client/src/session.rs +++ b/crates/irtt-client/src/session.rs @@ -48,6 +48,11 @@ pub(crate) fn validate_negotiated_params( }); } validate_duration_restriction(requested.duration_ns, returned.duration_ns)?; + if returned.length < 0 { + return Err(ClientError::NegotiationRejected { + reason: "length must be non-negative".to_owned(), + }); + } if returned.length > requested.length { return Err(ClientError::NegotiationRejected { reason: "length increased".to_owned(),