fix(proto): floor negative echo lengths

This commit is contained in:
Nils Andreas Svee committed 2026-08-12 17:16:03 +07:00
1 parent 2e2db4d3e0
commit 68ed5c6e2e
12 files changed
+107 -95

No files matched your search

+30 -4
View File
@@ -305,6 +305,32 @@ fn echo_payload_is_copied_zero_filled_and_bounded_in_both_directions() {
);
}
#[test]
fn a_negative_negotiated_length_still_encodes_in_both_directions() {
// A server accepts a negative negotiated length during open and returns it
// unchanged, so a live session can hold one and must stay executable. There
// is no datagram shorter than none, so both directions fall back to the
// mandatory field block — header (4) + token (8) + sequence (4) — exactly
// as a zero length would.
let params = Params {
length: -4096,
..Params::default()
};
assert_eq!(echo_packet_len(false, &params), 16);
let request = encode_request(echo_request(&params, &[]), None)
.expect("a negative negotiated length must still encode a request");
assert_eq!(request.len(), 16);
let reply = encode_echo_reply(&echo_reply(&params, FLAG_REPLY), &params, None)
.expect("a negative negotiated length must still encode a reply");
assert_eq!(reply.len(), 16);
assert_eq!(
decode_echo_reply(&reply, &params, None).unwrap().token,
TOKEN
);
}
// ---------- Upstream midpoint ECHO-reply compatibility ----------
//
// Verified upstream irtt 0.9.1 behavior: for single-clock
@@ -346,7 +372,7 @@ fn midpoint_params(clock: Clock, payload_space: usize) -> Params {
fn midpoint_compat_len(params: &Params, hmac: bool) -> usize {
let compat_header = PacketLayout::echo(hmac, params).header_len() + 8;
compat_header.max(echo_packet_len(hmac, params).unwrap())
compat_header.max(echo_packet_len(hmac, params))
}
/// Hand-builds upstream's dual-midpoint ECHO reply: both midpoint fields on
@@ -399,7 +425,7 @@ fn midpoint_dual_field_reply_is_accepted_wherever_length_identifies_it() {
for (payload_space, expected_extra) in [(0, 8), (1, 7), (4, 4), (7, 1)] {
for clock in [Clock::Wall, Clock::Monotonic] {
let params = midpoint_params(clock, payload_space);
let normal_len = echo_packet_len(false, &params).unwrap();
let normal_len = echo_packet_len(false, &params);
let packet = build_midpoint_dual_field_reply(&params, FLAG_REPLY, 3, (111, 222), None);
assert_eq!(
packet.len(),
@@ -438,7 +464,7 @@ fn midpoint_dual_field_reply_of_equal_length_is_accepted_but_not_correctable() {
for payload_space in [8, 64] {
for clock in [Clock::Wall, Clock::Monotonic] {
let params = midpoint_params(clock, payload_space);
let normal_len = echo_packet_len(false, &params).unwrap();
let normal_len = echo_packet_len(false, &params);
let packet = build_midpoint_dual_field_reply(&params, FLAG_REPLY, 4, (111, 222), None);
assert_eq!(
packet.len(),
@@ -491,7 +517,7 @@ fn midpoint_dual_field_reply_authenticates_over_full_packet() {
fn only_the_exact_compat_length_is_accepted_as_an_extension() {
let params = midpoint_params(Clock::Wall, 0);
let packet = build_midpoint_dual_field_reply(&params, FLAG_REPLY, 1, (10, 20), None);
let expected_len = echo_packet_len(false, &params).unwrap();
let expected_len = echo_packet_len(false, &params);
assert_eq!(packet.len(), expected_len + 8);
// Every other length around the compatibility size stays rejected,