Coverage Report

Created: 2026-04-01 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/neqo/neqo-http3/src/frames/reader.rs
Line
Count
Source
1
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4
// option. This file may not be copied, modified, or distributed
5
// except according to those terms.
6
7
use std::{cmp::min, fmt::Debug, time::Instant};
8
9
use neqo_common::{
10
    Decoder, IncrementalDecoderBuffer, IncrementalDecoderIgnore, IncrementalDecoderUint,
11
    hex_snip_middle, hex_with_len, qtrace,
12
};
13
use neqo_transport::{Connection, StreamId};
14
15
use super::hframe::HFrameType;
16
use crate::{Error, RecvStream, Res};
17
18
const MAX_READ_SIZE: usize = 2048; // Given a practical MTU of 1500 bytes, this seems reasonable.
19
20
pub trait FrameDecoder<T> {
21
    /// Fuzzing corpus name for this frame type. If `Some`, decoded frames will be
22
    /// written to the fuzzing corpus with this name.
23
    #[cfg(feature = "build-fuzzing-corpus")]
24
    const FUZZING_CORPUS: Option<&'static str> = None;
25
26
    fn is_known_type(frame_type: HFrameType) -> bool;
27
28
    /// # Errors
29
    ///
30
    /// Returns `HttpFrameUnexpected` if frames is not allowed, i.e. is a `H3_RESERVED_FRAME_TYPES`.
31
1.83M
    fn frame_type_allowed(_frame_type: HFrameType) -> Res<()> {
32
1.83M
        Ok(())
33
1.83M
    }
<neqo_http3::frames::wtframe::WebTransportFrame as neqo_http3::frames::reader::FrameDecoder<neqo_http3::frames::wtframe::WebTransportFrame>>::frame_type_allowed
Line
Count
Source
31
1.83M
    fn frame_type_allowed(_frame_type: HFrameType) -> Res<()> {
32
1.83M
        Ok(())
33
1.83M
    }
Unexecuted instantiation: <neqo_http3::frames::capsule::Capsule as neqo_http3::frames::reader::FrameDecoder<neqo_http3::frames::capsule::Capsule>>::frame_type_allowed
Unexecuted instantiation: <neqo_http3::frames::wtframe::WebTransportFrame as neqo_http3::frames::reader::FrameDecoder<neqo_http3::frames::wtframe::WebTransportFrame>>::frame_type_allowed
34
35
    /// # Errors
36
    ///
37
    /// If a frame cannot be properly decoded.
38
    fn decode(frame_type: HFrameType, frame_len: u64, data: Option<&[u8]>) -> Res<Option<T>>;
39
}
40
41
#[expect(clippy::module_name_repetitions, reason = "This is OK.")]
42
pub trait StreamReader {
43
    /// # Errors
44
    ///
45
    /// An error may happen while reading a stream, e.g. early close, protocol error, etc.
46
    /// Return an error if the stream was closed on the transport layer, but that information is not
47
    /// yet consumed on the  http/3 layer.
48
    fn read_data(&mut self, buf: &mut [u8], now: Instant) -> Res<(usize, bool)>;
49
}
50
51
pub struct StreamReaderConnectionWrapper<'a> {
52
    conn: &'a mut Connection,
53
    stream_id: StreamId,
54
}
55
56
impl<'a> StreamReaderConnectionWrapper<'a> {
57
0
    pub const fn new(conn: &'a mut Connection, stream_id: StreamId) -> Self {
58
0
        Self { conn, stream_id }
59
0
    }
60
}
61
62
impl StreamReader for StreamReaderConnectionWrapper<'_> {
63
    /// # Errors
64
    ///
65
    /// An error may happen while reading a stream, e.g. early close, protocol error, etc.
66
0
    fn read_data(&mut self, buf: &mut [u8], _now: Instant) -> Res<(usize, bool)> {
67
0
        let res = self.conn.stream_recv(self.stream_id, buf)?;
68
0
        Ok(res)
69
0
    }
70
}
71
72
pub struct StreamReaderRecvStreamWrapper<'a> {
73
    recv_stream: &'a mut Box<dyn RecvStream>,
74
    conn: &'a mut Connection,
75
}
76
77
impl<'a> StreamReaderRecvStreamWrapper<'a> {
78
    #[cfg_attr(fuzzing, expect(private_interfaces, reason = "OK for fuzzing."))]
79
0
    pub fn new(conn: &'a mut Connection, recv_stream: &'a mut Box<dyn RecvStream>) -> Self {
80
0
        Self { recv_stream, conn }
81
0
    }
82
}
83
84
impl StreamReader for StreamReaderRecvStreamWrapper<'_> {
85
    /// # Errors
86
    ///
87
    /// An error may happen while reading a stream, e.g. early close, protocol error, etc.
88
0
    fn read_data(&mut self, buf: &mut [u8], now: Instant) -> Res<(usize, bool)> {
89
0
        self.recv_stream.read_data(self.conn, buf, now)
90
0
    }
91
}
92
93
#[derive(Clone, Debug)]
94
enum FrameReaderState {
95
    GetType { decoder: IncrementalDecoderUint },
96
    GetLength { decoder: IncrementalDecoderUint },
97
    GetData { decoder: IncrementalDecoderBuffer },
98
    UnknownFrameDischargeData { decoder: IncrementalDecoderIgnore },
99
}
100
101
#[expect(clippy::module_name_repetitions, reason = "This is OK.")]
102
pub struct FrameReader {
103
    state: FrameReaderState,
104
    frame_type: HFrameType,
105
    frame_len: u64,
106
    buffer: [u8; MAX_READ_SIZE],
107
}
108
109
impl Debug for FrameReader {
110
0
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111
0
        let frame_len = self
112
0
            .frame_len
113
0
            .try_into()
114
0
            .unwrap_or(usize::MAX)
115
0
            .min(self.buffer.len());
116
0
        f.debug_struct("FrameReader")
117
0
            .field("state", &self.state)
118
0
            .field("frame_type", &self.frame_type)
119
0
            .field("frame", &hex_snip_middle(&self.buffer[..frame_len]))
120
0
            .finish()
121
0
    }
122
}
123
124
impl FrameReader {
125
    #[must_use]
126
6.05k
    pub fn new() -> Self {
127
6.05k
        Self {
128
6.05k
            state: FrameReaderState::GetType {
129
6.05k
                decoder: IncrementalDecoderUint::default(),
130
6.05k
            },
131
6.05k
            frame_type: HFrameType(u64::MAX),
132
6.05k
            frame_len: 0,
133
6.05k
            buffer: [0; MAX_READ_SIZE],
134
6.05k
        }
135
6.05k
    }
136
137
    #[must_use]
138
0
    pub fn new_with_type(frame_type: HFrameType) -> Self {
139
0
        Self {
140
0
            state: FrameReaderState::GetLength {
141
0
                decoder: IncrementalDecoderUint::default(),
142
0
            },
143
0
            frame_type,
144
0
            frame_len: 0,
145
0
            buffer: [0; MAX_READ_SIZE],
146
0
        }
147
0
    }
148
149
1.91M
    fn reset(&mut self) {
150
1.91M
        self.state = FrameReaderState::GetType {
151
1.91M
            decoder: IncrementalDecoderUint::default(),
152
1.91M
        };
153
1.91M
    }
154
155
4.04M
    fn min_remaining(&self) -> usize {
156
4.04M
        match &self.state {
157
1.92M
            FrameReaderState::GetType { decoder } | FrameReaderState::GetLength { decoder } => {
158
3.85M
                decoder.min_remaining()
159
            }
160
57.2k
            FrameReaderState::GetData { decoder } => decoder.min_remaining(),
161
138k
            FrameReaderState::UnknownFrameDischargeData { decoder } => decoder.min_remaining(),
162
        }
163
4.04M
    }
164
165
1.57k
    const fn decoding_in_progress(&self) -> bool {
166
1.57k
        if let FrameReaderState::GetType { decoder } = &self.state {
167
437
            decoder.decoding_in_progress()
168
        } else {
169
1.14k
            true
170
        }
171
1.57k
    }
172
173
    /// Returns true if QUIC stream was closed.
174
    ///
175
    /// # Errors
176
    ///
177
    /// May return `HttpFrame` if a frame cannot be decoded.
178
    /// and `TransportStreamDoesNotExist` if `stream_recv` fails.
179
6.05k
    pub fn receive<T: FrameDecoder<T>>(
180
6.05k
        &mut self,
181
6.05k
        stream_reader: &mut dyn StreamReader,
182
6.05k
        now: Instant,
183
6.05k
    ) -> Res<(Option<T>, bool)> {
184
        loop {
185
4.04M
            let to_read = min(self.min_remaining(), self.buffer.len());
186
4.04M
            let (output, read, fin) = match stream_reader
187
4.04M
                .read_data(&mut self.buffer[..to_read], now)
188
4.04M
                .map_err(|e| Error::map_stream_recv_errors(&e))?
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::receive::<neqo_http3::frames::wtframe::WebTransportFrame>::{closure#0}
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::receive::<neqo_http3::frames::hframe::HFrame>::{closure#0}
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::receive::<neqo_http3::frames::capsule::Capsule>::{closure#0}
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::receive::<neqo_http3::frames::wtframe::WebTransportFrame>::{closure#0}
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::receive::<neqo_http3::frames::hframe::HFrame>::{closure#0}
189
            {
190
0
                (0, f) => (None, false, f),
191
4.04M
                (amount, f) => {
192
4.04M
                    qtrace!("FrameReader::receive: reading {amount} byte, fin={f}");
193
4.04M
                    (self.consume::<T>(amount)?, true, f)
194
                }
195
            };
196
197
4.04M
            if output.is_some() {
198
1.73k
                break Ok((output, fin));
199
4.04M
            }
200
201
4.04M
            if fin {
202
1.57k
                if self.decoding_in_progress() {
203
1.26k
                    break Err(Error::HttpFrame);
204
312
                }
205
312
                break Ok((None, fin));
206
4.04M
            }
207
208
4.04M
            if !read {
209
                // There was no new data, exit the loop.
210
0
                break Ok((None, false));
211
4.04M
            }
212
        }
213
6.05k
    }
<neqo_http3::frames::reader::FrameReader>::receive::<neqo_http3::frames::wtframe::WebTransportFrame>
Line
Count
Source
179
888
    pub fn receive<T: FrameDecoder<T>>(
180
888
        &mut self,
181
888
        stream_reader: &mut dyn StreamReader,
182
888
        now: Instant,
183
888
    ) -> Res<(Option<T>, bool)> {
184
        loop {
185
3.73M
            let to_read = min(self.min_remaining(), self.buffer.len());
186
3.73M
            let (output, read, fin) = match stream_reader
187
3.73M
                .read_data(&mut self.buffer[..to_read], now)
188
3.73M
                .map_err(|e| Error::map_stream_recv_errors(&e))?
189
            {
190
0
                (0, f) => (None, false, f),
191
3.73M
                (amount, f) => {
192
3.73M
                    qtrace!("FrameReader::receive: reading {amount} byte, fin={f}");
193
3.73M
                    (self.consume::<T>(amount)?, true, f)
194
                }
195
            };
196
197
3.73M
            if output.is_some() {
198
69
                break Ok((output, fin));
199
3.73M
            }
200
201
3.73M
            if fin {
202
724
                if self.decoding_in_progress() {
203
614
                    break Err(Error::HttpFrame);
204
110
                }
205
110
                break Ok((None, fin));
206
3.73M
            }
207
208
3.73M
            if !read {
209
                // There was no new data, exit the loop.
210
0
                break Ok((None, false));
211
3.73M
            }
212
        }
213
888
    }
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::receive::<neqo_http3::frames::hframe::HFrame>
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::receive::<neqo_http3::frames::capsule::Capsule>
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::receive::<neqo_http3::frames::wtframe::WebTransportFrame>
<neqo_http3::frames::reader::FrameReader>::receive::<neqo_http3::frames::hframe::HFrame>
Line
Count
Source
179
5.16k
    pub fn receive<T: FrameDecoder<T>>(
180
5.16k
        &mut self,
181
5.16k
        stream_reader: &mut dyn StreamReader,
182
5.16k
        now: Instant,
183
5.16k
    ) -> Res<(Option<T>, bool)> {
184
        loop {
185
311k
            let to_read = min(self.min_remaining(), self.buffer.len());
186
311k
            let (output, read, fin) = match stream_reader
187
311k
                .read_data(&mut self.buffer[..to_read], now)
188
311k
                .map_err(|e| Error::map_stream_recv_errors(&e))?
189
            {
190
0
                (0, f) => (None, false, f),
191
311k
                (amount, f) => {
192
311k
                    qtrace!("FrameReader::receive: reading {amount} byte, fin={f}");
193
311k
                    (self.consume::<T>(amount)?, true, f)
194
                }
195
            };
196
197
309k
            if output.is_some() {
198
1.66k
                break Ok((output, fin));
199
307k
            }
200
201
307k
            if fin {
202
855
                if self.decoding_in_progress() {
203
653
                    break Err(Error::HttpFrame);
204
202
                }
205
202
                break Ok((None, fin));
206
306k
            }
207
208
306k
            if !read {
209
                // There was no new data, exit the loop.
210
0
                break Ok((None, false));
211
306k
            }
212
        }
213
5.16k
    }
214
215
    /// # Errors
216
    ///
217
    /// May return `HttpFrame` if a frame cannot be decoded.
218
4.04M
    fn consume<T: FrameDecoder<T>>(&mut self, amount: usize) -> Res<Option<T>> {
219
4.04M
        let mut input = Decoder::from(&self.buffer[..amount]);
220
4.04M
        match &mut self.state {
221
1.92M
            FrameReaderState::GetType { decoder } => {
222
1.92M
                if let Some(v) = decoder.consume(&mut input) {
223
1.92M
                    qtrace!("FrameReader::receive: read frame type {v}");
224
1.92M
                    self.frame_type_decoded::<T>(HFrameType(v))?;
225
6.23k
                }
226
            }
227
1.92M
            FrameReaderState::GetLength { decoder } => {
228
1.92M
                if let Some(len) = decoder.consume(&mut input) {
229
1.92M
                    qtrace!(
230
                        "FrameReader::receive: frame type {:?} length {len}",
231
                        self.frame_type
232
                    );
233
1.92M
                    return self.frame_length_decoded::<T>(len);
234
3.86k
                }
235
            }
236
57.2k
            FrameReaderState::GetData { decoder } => {
237
57.2k
                if let Some(data) = decoder.consume(&mut input) {
238
4.44k
                    qtrace!(
239
                        "received frame {:?}: {}",
240
                        self.frame_type,
241
0
                        hex_with_len(&data[..])
242
                    );
243
4.44k
                    return self.frame_data_decoded::<T>(&data);
244
52.7k
                }
245
            }
246
138k
            FrameReaderState::UnknownFrameDischargeData { decoder } => {
247
138k
                if decoder.consume(&mut input) {
248
134k
                    self.reset();
249
134k
                }
250
            }
251
        }
252
2.12M
        Ok(None)
253
4.04M
    }
<neqo_http3::frames::reader::FrameReader>::consume::<neqo_http3::frames::wtframe::WebTransportFrame>
Line
Count
Source
218
3.73M
    fn consume<T: FrameDecoder<T>>(&mut self, amount: usize) -> Res<Option<T>> {
219
3.73M
        let mut input = Decoder::from(&self.buffer[..amount]);
220
3.73M
        match &mut self.state {
221
1.83M
            FrameReaderState::GetType { decoder } => {
222
1.83M
                if let Some(v) = decoder.consume(&mut input) {
223
1.83M
                    qtrace!("FrameReader::receive: read frame type {v}");
224
1.83M
                    self.frame_type_decoded::<T>(HFrameType(v))?;
225
1.68k
                }
226
            }
227
1.83M
            FrameReaderState::GetLength { decoder } => {
228
1.83M
                if let Some(len) = decoder.consume(&mut input) {
229
1.83M
                    qtrace!(
230
                        "FrameReader::receive: frame type {:?} length {len}",
231
                        self.frame_type
232
                    );
233
1.83M
                    return self.frame_length_decoded::<T>(len);
234
1.33k
                }
235
            }
236
4.92k
            FrameReaderState::GetData { decoder } => {
237
4.92k
                if let Some(data) = decoder.consume(&mut input) {
238
161
                    qtrace!(
239
                        "received frame {:?}: {}",
240
                        self.frame_type,
241
0
                        hex_with_len(&data[..])
242
                    );
243
161
                    return self.frame_data_decoded::<T>(&data);
244
4.76k
                }
245
            }
246
57.7k
            FrameReaderState::UnknownFrameDischargeData { decoder } => {
247
57.7k
                if decoder.consume(&mut input) {
248
55.2k
                    self.reset();
249
55.2k
                }
250
            }
251
        }
252
1.90M
        Ok(None)
253
3.73M
    }
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::consume::<neqo_http3::frames::hframe::HFrame>
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::consume::<neqo_http3::frames::capsule::Capsule>
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::consume::<neqo_http3::frames::wtframe::WebTransportFrame>
<neqo_http3::frames::reader::FrameReader>::consume::<neqo_http3::frames::hframe::HFrame>
Line
Count
Source
218
311k
    fn consume<T: FrameDecoder<T>>(&mut self, amount: usize) -> Res<Option<T>> {
219
311k
        let mut input = Decoder::from(&self.buffer[..amount]);
220
311k
        match &mut self.state {
221
90.6k
            FrameReaderState::GetType { decoder } => {
222
90.6k
                if let Some(v) = decoder.consume(&mut input) {
223
86.1k
                    qtrace!("FrameReader::receive: read frame type {v}");
224
86.1k
                    self.frame_type_decoded::<T>(HFrameType(v))?;
225
4.55k
                }
226
            }
227
88.5k
            FrameReaderState::GetLength { decoder } => {
228
88.5k
                if let Some(len) = decoder.consume(&mut input) {
229
85.9k
                    qtrace!(
230
                        "FrameReader::receive: frame type {:?} length {len}",
231
                        self.frame_type
232
                    );
233
85.9k
                    return self.frame_length_decoded::<T>(len);
234
2.52k
                }
235
            }
236
52.3k
            FrameReaderState::GetData { decoder } => {
237
52.3k
                if let Some(data) = decoder.consume(&mut input) {
238
4.28k
                    qtrace!(
239
                        "received frame {:?}: {}",
240
                        self.frame_type,
241
0
                        hex_with_len(&data[..])
242
                    );
243
4.28k
                    return self.frame_data_decoded::<T>(&data);
244
48.0k
                }
245
            }
246
80.3k
            FrameReaderState::UnknownFrameDischargeData { decoder } => {
247
80.3k
                if decoder.consume(&mut input) {
248
79.4k
                    self.reset();
249
79.4k
                }
250
            }
251
        }
252
221k
        Ok(None)
253
311k
    }
254
1.92M
    fn frame_type_decoded<T: FrameDecoder<T>>(&mut self, frame_type: HFrameType) -> Res<()> {
255
1.92M
        T::frame_type_allowed(frame_type)?;
256
1.92M
        self.frame_type = frame_type;
257
1.92M
        self.state = FrameReaderState::GetLength {
258
1.92M
            decoder: IncrementalDecoderUint::default(),
259
1.92M
        };
260
1.92M
        Ok(())
261
1.92M
    }
<neqo_http3::frames::reader::FrameReader>::frame_type_decoded::<neqo_http3::frames::wtframe::WebTransportFrame>
Line
Count
Source
254
1.83M
    fn frame_type_decoded<T: FrameDecoder<T>>(&mut self, frame_type: HFrameType) -> Res<()> {
255
1.83M
        T::frame_type_allowed(frame_type)?;
256
1.83M
        self.frame_type = frame_type;
257
1.83M
        self.state = FrameReaderState::GetLength {
258
1.83M
            decoder: IncrementalDecoderUint::default(),
259
1.83M
        };
260
1.83M
        Ok(())
261
1.83M
    }
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::frame_type_decoded::<neqo_http3::frames::hframe::HFrame>
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::frame_type_decoded::<neqo_http3::frames::capsule::Capsule>
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::frame_type_decoded::<neqo_http3::frames::wtframe::WebTransportFrame>
<neqo_http3::frames::reader::FrameReader>::frame_type_decoded::<neqo_http3::frames::hframe::HFrame>
Line
Count
Source
254
86.1k
    fn frame_type_decoded<T: FrameDecoder<T>>(&mut self, frame_type: HFrameType) -> Res<()> {
255
86.1k
        T::frame_type_allowed(frame_type)?;
256
86.1k
        self.frame_type = frame_type;
257
86.1k
        self.state = FrameReaderState::GetLength {
258
86.1k
            decoder: IncrementalDecoderUint::default(),
259
86.1k
        };
260
86.1k
        Ok(())
261
86.1k
    }
262
263
1.92M
    fn frame_length_decoded<T: FrameDecoder<T>>(&mut self, len: u64) -> Res<Option<T>> {
264
1.92M
        self.frame_len = len;
265
1.92M
        match T::decode(
266
1.92M
            self.frame_type,
267
1.92M
            self.frame_len,
268
1.92M
            if len > 0 { None } else { Some(&[]) },
269
10
        )? {
270
17
            Some(f) => {
271
                #[cfg(feature = "build-fuzzing-corpus")]
272
                if let Some(corpus) = T::FUZZING_CORPUS {
273
                    // Write zero-length frames to the fuzzing corpus to test parsing of frames with
274
                    // only type and length fields.
275
                    self.write_item_to_fuzzing_corpus(corpus, None);
276
                }
277
17
                self.reset();
278
17
                return Ok(Some(f));
279
            }
280
            None => {
281
1.92M
                if T::is_known_type(self.frame_type) {
282
4.83k
                    self.state = FrameReaderState::GetData {
283
4.83k
                        decoder: IncrementalDecoderBuffer::new(
284
4.83k
                            usize::try_from(len).or(Err(Error::HttpFrame))?,
285
                        ),
286
                    };
287
1.91M
                } else if self.frame_len == 0 {
288
1.78M
                    self.reset();
289
1.78M
                } else {
290
135k
                    self.state = FrameReaderState::UnknownFrameDischargeData {
291
135k
                        decoder: IncrementalDecoderIgnore::new(
292
135k
                            usize::try_from(len).or(Err(Error::HttpFrame))?,
293
                        ),
294
                    };
295
                }
296
            }
297
        }
298
1.92M
        Ok(None)
299
1.92M
    }
<neqo_http3::frames::reader::FrameReader>::frame_length_decoded::<neqo_http3::frames::wtframe::WebTransportFrame>
Line
Count
Source
263
1.83M
    fn frame_length_decoded<T: FrameDecoder<T>>(&mut self, len: u64) -> Res<Option<T>> {
264
1.83M
        self.frame_len = len;
265
1.83M
        match T::decode(
266
1.83M
            self.frame_type,
267
1.83M
            self.frame_len,
268
1.83M
            if len > 0 { None } else { Some(&[]) },
269
3
        )? {
270
0
            Some(f) => {
271
                #[cfg(feature = "build-fuzzing-corpus")]
272
                if let Some(corpus) = T::FUZZING_CORPUS {
273
                    // Write zero-length frames to the fuzzing corpus to test parsing of frames with
274
                    // only type and length fields.
275
                    self.write_item_to_fuzzing_corpus(corpus, None);
276
                }
277
0
                self.reset();
278
0
                return Ok(Some(f));
279
            }
280
            None => {
281
1.83M
                if T::is_known_type(self.frame_type) {
282
358
                    self.state = FrameReaderState::GetData {
283
358
                        decoder: IncrementalDecoderBuffer::new(
284
358
                            usize::try_from(len).or(Err(Error::HttpFrame))?,
285
                        ),
286
                    };
287
1.83M
                } else if self.frame_len == 0 {
288
1.77M
                    self.reset();
289
1.77M
                } else {
290
55.5k
                    self.state = FrameReaderState::UnknownFrameDischargeData {
291
55.5k
                        decoder: IncrementalDecoderIgnore::new(
292
55.5k
                            usize::try_from(len).or(Err(Error::HttpFrame))?,
293
                        ),
294
                    };
295
                }
296
            }
297
        }
298
1.83M
        Ok(None)
299
1.83M
    }
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::frame_length_decoded::<neqo_http3::frames::hframe::HFrame>
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::frame_length_decoded::<neqo_http3::frames::capsule::Capsule>
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::frame_length_decoded::<neqo_http3::frames::wtframe::WebTransportFrame>
<neqo_http3::frames::reader::FrameReader>::frame_length_decoded::<neqo_http3::frames::hframe::HFrame>
Line
Count
Source
263
85.9k
    fn frame_length_decoded<T: FrameDecoder<T>>(&mut self, len: u64) -> Res<Option<T>> {
264
85.9k
        self.frame_len = len;
265
85.9k
        match T::decode(
266
85.9k
            self.frame_type,
267
85.9k
            self.frame_len,
268
85.9k
            if len > 0 { None } else { Some(&[]) },
269
7
        )? {
270
17
            Some(f) => {
271
                #[cfg(feature = "build-fuzzing-corpus")]
272
                if let Some(corpus) = T::FUZZING_CORPUS {
273
                    // Write zero-length frames to the fuzzing corpus to test parsing of frames with
274
                    // only type and length fields.
275
                    self.write_item_to_fuzzing_corpus(corpus, None);
276
                }
277
17
                self.reset();
278
17
                return Ok(Some(f));
279
            }
280
            None => {
281
85.9k
                if T::is_known_type(self.frame_type) {
282
4.47k
                    self.state = FrameReaderState::GetData {
283
4.47k
                        decoder: IncrementalDecoderBuffer::new(
284
4.47k
                            usize::try_from(len).or(Err(Error::HttpFrame))?,
285
                        ),
286
                    };
287
81.4k
                } else if self.frame_len == 0 {
288
1.73k
                    self.reset();
289
1.73k
                } else {
290
79.7k
                    self.state = FrameReaderState::UnknownFrameDischargeData {
291
79.7k
                        decoder: IncrementalDecoderIgnore::new(
292
79.7k
                            usize::try_from(len).or(Err(Error::HttpFrame))?,
293
                        ),
294
                    };
295
                }
296
            }
297
        }
298
85.9k
        Ok(None)
299
85.9k
    }
300
301
4.44k
    fn frame_data_decoded<T: FrameDecoder<T>>(&mut self, data: &[u8]) -> Res<Option<T>> {
302
        #[cfg(feature = "build-fuzzing-corpus")]
303
        if let Some(corpus) = T::FUZZING_CORPUS {
304
            self.write_item_to_fuzzing_corpus(corpus, Some(data));
305
        }
306
307
4.44k
        let res = T::decode(self.frame_type, self.frame_len, Some(data))?;
308
1.71k
        self.reset();
309
1.71k
        Ok(res)
310
4.44k
    }
<neqo_http3::frames::reader::FrameReader>::frame_data_decoded::<neqo_http3::frames::wtframe::WebTransportFrame>
Line
Count
Source
301
161
    fn frame_data_decoded<T: FrameDecoder<T>>(&mut self, data: &[u8]) -> Res<Option<T>> {
302
        #[cfg(feature = "build-fuzzing-corpus")]
303
        if let Some(corpus) = T::FUZZING_CORPUS {
304
            self.write_item_to_fuzzing_corpus(corpus, Some(data));
305
        }
306
307
161
        let res = T::decode(self.frame_type, self.frame_len, Some(data))?;
308
69
        self.reset();
309
69
        Ok(res)
310
161
    }
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::frame_data_decoded::<neqo_http3::frames::hframe::HFrame>
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::frame_data_decoded::<neqo_http3::frames::capsule::Capsule>
Unexecuted instantiation: <neqo_http3::frames::reader::FrameReader>::frame_data_decoded::<neqo_http3::frames::wtframe::WebTransportFrame>
<neqo_http3::frames::reader::FrameReader>::frame_data_decoded::<neqo_http3::frames::hframe::HFrame>
Line
Count
Source
301
4.28k
    fn frame_data_decoded<T: FrameDecoder<T>>(&mut self, data: &[u8]) -> Res<Option<T>> {
302
        #[cfg(feature = "build-fuzzing-corpus")]
303
        if let Some(corpus) = T::FUZZING_CORPUS {
304
            self.write_item_to_fuzzing_corpus(corpus, Some(data));
305
        }
306
307
4.28k
        let res = T::decode(self.frame_type, self.frame_len, Some(data))?;
308
1.64k
        self.reset();
309
1.64k
        Ok(res)
310
4.28k
    }
311
312
    #[cfg(feature = "build-fuzzing-corpus")]
313
    /// Write `HFrame` data to indicated fuzzing corpus.
314
    ///
315
    /// The output consists of the varint-encoded frame type and length, followed by the optional
316
    /// payload data.
317
    fn write_item_to_fuzzing_corpus(&self, corpus: &str, data: Option<&[u8]>) {
318
        // We need to include the frame type and length varints before the data
319
        // to create a complete frame that the fuzzer can process.
320
        let mut encoder = neqo_common::Encoder::default();
321
        encoder.encode_varint(self.frame_type.0);
322
        encoder.encode_varint(self.frame_len);
323
        if let Some(d) = data {
324
            encoder.encode(d);
325
        }
326
        neqo_common::write_item_to_fuzzing_corpus(corpus, encoder.as_ref());
327
    }
328
}