Skip to content

Commit f81c2fa

Browse files
djcRalith
authored andcommitted
More principled error handling for invalid frames
1 parent 0af891e commit f81c2fa

File tree

4 files changed

+38
-24
lines changed

4 files changed

+38
-24
lines changed

quinn-proto/src/connection/mod.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,7 +2192,15 @@ impl Connection {
21922192
return Ok(());
21932193
}
21942194
State::Closed(_) => {
2195-
for frame in frame::Iter::new(packet.payload.freeze()) {
2195+
for result in frame::Iter::new(packet.payload.freeze()) {
2196+
let frame = match result {
2197+
Ok(frame) => frame,
2198+
Err(err) => {
2199+
debug!("frame decoding error: {err:?}");
2200+
continue;
2201+
}
2202+
};
2203+
21962204
if let Frame::Padding = frame {
21972205
continue;
21982206
};
@@ -2433,7 +2441,8 @@ impl Connection {
24332441
debug_assert_ne!(packet.header.space(), SpaceId::Data);
24342442
let payload_len = packet.payload.len();
24352443
let mut ack_eliciting = false;
2436-
for frame in frame::Iter::new(packet.payload.freeze()) {
2444+
for result in frame::Iter::new(packet.payload.freeze()) {
2445+
let frame = result?;
24372446
let span = match frame {
24382447
Frame::Padding => continue,
24392448
_ => Some(trace_span!("frame", ty = %frame.ty())),
@@ -2458,11 +2467,6 @@ impl Connection {
24582467
self.state = State::Draining;
24592468
return Ok(());
24602469
}
2461-
Frame::Invalid { ty, reason } => {
2462-
let mut err = TransportError::FRAME_ENCODING_ERROR(reason);
2463-
err.frame = Some(ty);
2464-
return Err(err);
2465-
}
24662470
_ => {
24672471
let mut err =
24682472
TransportError::PROTOCOL_VIOLATION("illegal frame type in handshake");
@@ -2495,7 +2499,8 @@ impl Connection {
24952499
let mut close = None;
24962500
let payload_len = payload.len();
24972501
let mut ack_eliciting = false;
2498-
for frame in frame::Iter::new(payload) {
2502+
for result in frame::Iter::new(payload) {
2503+
let frame = result?;
24992504
let span = match frame {
25002505
Frame::Padding => continue,
25012506
_ => Some(trace_span!("frame", ty = %frame.ty())),
@@ -2543,11 +2548,6 @@ impl Connection {
25432548
}
25442549
}
25452550
match frame {
2546-
Frame::Invalid { ty, reason } => {
2547-
let mut err = TransportError::FRAME_ENCODING_ERROR(reason);
2548-
err.frame = Some(ty);
2549-
return Err(err);
2550-
}
25512551
Frame::Crypto(frame) => {
25522552
self.read_crypto(SpaceId::Data, &frame, payload_len)?;
25532553
}

quinn-proto/src/connection/stats.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ impl FrameStats {
8686
Frame::AckFrequency(_) => self.ack_frequency += 1,
8787
Frame::ImmediateAck => self.immediate_ack += 1,
8888
Frame::HandshakeDone => self.handshake_done += 1,
89-
Frame::Invalid { .. } => {}
9089
}
9190
}
9291
}

quinn-proto/src/frame.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ pub(crate) enum Frame {
162162
Datagram(Datagram),
163163
AckFrequency(AckFrequency),
164164
ImmediateAck,
165-
Invalid { ty: Type, reason: &'static str },
166165
HandshakeDone,
167166
}
168167

@@ -204,7 +203,6 @@ impl Frame {
204203
Datagram(_) => Type(*DATAGRAM_TYS.start()),
205204
AckFrequency(_) => Type::ACK_FREQUENCY,
206205
ImmediateAck => Type::IMMEDIATE_ACK,
207-
Invalid { ty, .. } => ty,
208206
HandshakeDone => Type::HANDSHAKE_DONE,
209207
}
210208
}
@@ -734,25 +732,39 @@ impl Iter {
734732
}
735733

736734
impl Iterator for Iter {
737-
type Item = Frame;
735+
type Item = Result<Frame, InvalidFrame>;
738736
fn next(&mut self) -> Option<Self::Item> {
739737
if !self.bytes.has_remaining() {
740738
return None;
741739
}
742740
match self.try_next() {
743-
Ok(x) => Some(x),
741+
Ok(x) => Some(Ok(x)),
744742
Err(e) => {
745743
// Corrupt frame, skip it and everything that follows
746744
self.bytes = io::Cursor::new(Bytes::new());
747-
Some(Frame::Invalid {
748-
ty: self.last_ty.unwrap(),
745+
Some(Err(InvalidFrame {
746+
ty: self.last_ty,
749747
reason: e.reason(),
750-
})
748+
}))
751749
}
752750
}
753751
}
754752
}
755753

754+
#[derive(Debug)]
755+
pub(crate) struct InvalidFrame {
756+
pub(crate) ty: Option<Type>,
757+
pub(crate) reason: &'static str,
758+
}
759+
760+
impl From<InvalidFrame> for TransportError {
761+
fn from(err: InvalidFrame) -> Self {
762+
let mut te = Self::FRAME_ENCODING_ERROR(err.reason);
763+
te.frame = err.ty;
764+
te
765+
}
766+
}
767+
756768
fn scan_ack_blocks(buf: &mut io::Cursor<Bytes>, largest: u64, n: usize) -> Result<(), IterErr> {
757769
let first_block = buf.get_var()?;
758770
let mut smallest = largest.checked_sub(first_block).ok_or(IterErr::Malformed)?;
@@ -910,7 +922,9 @@ mod test {
910922
use assert_matches::assert_matches;
911923

912924
fn frames(buf: Vec<u8>) -> Vec<Frame> {
913-
Iter::new(Bytes::from(buf)).collect::<Vec<_>>()
925+
Iter::new(Bytes::from(buf))
926+
.collect::<Result<Vec<_>, _>>()
927+
.unwrap()
914928
}
915929

916930
#[test]

quinn-proto/src/tests/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2256,8 +2256,9 @@ fn single_ack_eliciting_packet_triggers_ack_after_delay() {
22562256

22572257
// The ACK delay is properly calculated
22582258
assert_eq!(pair.client.captured_packets.len(), 1);
2259-
let mut frames =
2260-
frame::Iter::new(pair.client.captured_packets.remove(0).into()).collect::<Vec<_>>();
2259+
let mut frames = frame::Iter::new(pair.client.captured_packets.remove(0).into())
2260+
.collect::<Result<Vec<_>, _>>()
2261+
.unwrap();
22612262
assert_eq!(frames.len(), 1);
22622263
if let Frame::Ack(ack) = frames.remove(0) {
22632264
let ack_delay_exp = TransportParameters::default().ack_delay_exponent;

0 commit comments

Comments
 (0)