fix(proto): reject packet lengths usize cannot represent

This commit is contained in:
Nils Andreas Svee committed 2026-08-12 20:05:01 +07:00
1 parent c833b0663d
commit 3845142d30
11 files changed
+102 -42

No files matched your search

+7 -2
View File
@@ -246,7 +246,7 @@ impl AsyncClient {
machine,
schedule: None,
remote,
recv_buffer: vec![0_u8; recv_buffer_size(false, None)],
recv_buffer: vec![0_u8; recv_buffer_size(false, None)?],
applied_traffic_class: None,
prepared_open: Some(prepared_open),
prepared_probe: None,
@@ -820,7 +820,12 @@ impl AsyncClient {
return Err(Box::new(PreparedAsyncOpenFailure { primary, machine }));
}
};
let recv_buffer_len = recv_buffer_size(self.machine.has_hmac(), Some(negotiated));
let recv_buffer_len = match recv_buffer_size(self.machine.has_hmac(), Some(negotiated)) {
Ok(size) => size,
Err(primary) => {
return Err(Box::new(PreparedAsyncOpenFailure { primary, machine }));
}
};
let negotiated_traffic_class = match u8::try_from(negotiated.params.dscp) {
Ok(traffic_class) => traffic_class,
Err(_) => {
+5 -2
View File
@@ -131,7 +131,7 @@ impl Client {
schedule: None,
socket,
remote,
recv_buffer: vec![0_u8; recv_buffer_size(false, None)],
recv_buffer: vec![0_u8; recv_buffer_size(false, None)?],
applied_traffic_class: None,
#[cfg(test)]
test_hooks: ClientTestHooks::default(),
@@ -530,7 +530,10 @@ impl Client {
Ok(schedule) => schedule,
Err(primary) => return Err(Box::new(PreparedClientOpenFailure { primary, machine })),
};
let recv_buffer_len = recv_buffer_size(self.runtime.has_hmac(), Some(negotiated));
let recv_buffer_len = match recv_buffer_size(self.runtime.has_hmac(), Some(negotiated)) {
Ok(size) => size,
Err(primary) => return Err(Box::new(PreparedClientOpenFailure { primary, machine })),
};
#[cfg(test)]
let recv_buffer_len = self
.test_hooks
@@ -1,8 +1,8 @@
use super::*;
pub(crate) use irtt_proto::echo_packet_len;
use irtt_proto::{
encode_echo_reply, encode_open_reply, flags::FLAG_OPEN, flags::FLAG_REPLY,
layout::PacketLayout, Clock, EchoReply, OpenReply, ReceivedStats, StampAt,
echo_packet_len as checked_echo_packet_len, encode_echo_reply, encode_open_reply,
flags::FLAG_OPEN, flags::FLAG_REPLY, layout::PacketLayout, Clock, EchoReply, OpenReply,
ReceivedStats, StampAt,
};
use std::{
net::UdpSocket,
@@ -72,6 +72,12 @@ pub(super) fn open_reply(
.unwrap()
}
/// Test params always name a representable length, so the platform
/// representability check cannot fire here.
pub(crate) fn echo_packet_len(hmac: bool, params: &Params) -> usize {
checked_echo_packet_len(hmac, params).expect("test params must have a representable length")
}
pub(super) fn echo_reply_packet(
token: u64,
seq: u32,
+14 -4
View File
@@ -823,13 +823,23 @@ impl SessionMachine {
}
}
pub(crate) fn recv_buffer_size(has_hmac: bool, negotiated: Option<&NegotiatedParams>) -> usize {
match negotiated {
Some(negotiated) => echo_packet_len(has_hmac, &negotiated.params)
/// Sizes the receive buffer for the negotiated layout.
///
/// Fallible only because a negotiated length wider than `usize` cannot name a
/// buffer at all. Negotiation already rejects a returned length that is
/// negative or larger than this client requested, and the requested length is a
/// `u32`, so the error is unreachable here in practice — it is propagated
/// rather than asserted away so that no 64-bit assumption is baked in.
pub(crate) fn recv_buffer_size(
has_hmac: bool,
negotiated: Option<&NegotiatedParams>,
) -> Result<usize, ClientError> {
Ok(match negotiated {
Some(negotiated) => echo_packet_len(has_hmac, &negotiated.params)?
.saturating_add(1)
.max(MIN_RECV_BUFFER_SIZE),
None => MIN_RECV_BUFFER_SIZE,
}
})
}
pub(crate) fn params_from_config(config: &ClientConfig) -> Result<Params, ClientError> {
+6 -3
View File
@@ -12,13 +12,12 @@ use std::{
use irtt_client::{Client, ClientConfig, ClientEvent, NegotiatedParams, OpenOutcome, SocketConfig};
use irtt_proto::{
compute_hmac_in_place, decode_request, encode_echo_reply, encode_open_reply, flags,
verify_packet_hmac, Clock, DecodedRequest, DecodedRequestKind, EchoReply, OpenReply,
compute_hmac_in_place, decode_request, echo_packet_len, encode_echo_reply, encode_open_reply,
flags, verify_packet_hmac, Clock, DecodedRequest, DecodedRequestKind, EchoReply, OpenReply,
PacketLayout, Params, ProtoError, ReceivedStats, ServerFill, StampAt, TimestampFields,
HMAC_SIZE, MAGIC, PROTOCOL_VERSION,
};
pub(super) use irtt_proto::echo_packet_len as test_echo_packet_len;
pub use real_irtt::RealIrtServer;
const HMAC_OFFSET: usize = 4;
@@ -534,6 +533,10 @@ fn open_reply(flags: u8, token: u64, params: &Params, hmac_key: Option<&[u8]>) -
.unwrap()
}
pub(super) fn test_echo_packet_len(hmac: bool, params: &Params) -> usize {
echo_packet_len(hmac, params).expect("test params must have a representable length")
}
fn echo_reply_packet(
token: u64,
seq: u32,