Coverage Report

Created: 2026-07-16 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/h2/src/hpack/decoder.rs
Line
Count
Source
1
use super::{header::BytesStr, huffman, Header};
2
use crate::frame;
3
4
use bytes::{Buf, Bytes, BytesMut};
5
use http::header;
6
use http::method::{self, Method};
7
use http::status::{self, StatusCode};
8
9
use std::cmp;
10
use std::collections::VecDeque;
11
use std::io::Cursor;
12
use std::ops::ControlFlow;
13
use std::str::Utf8Error;
14
15
/// Decodes headers using HPACK
16
#[derive(Debug)]
17
pub struct Decoder {
18
    // Protocol indicated that the max table size will update
19
    max_size_update: Option<usize>,
20
    last_max_update: usize,
21
    table: Table,
22
    buffer: BytesMut,
23
}
24
25
/// Represents all errors that can be encountered while performing the decoding
26
/// of an HPACK header set.
27
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
28
pub enum DecoderError {
29
    InvalidRepresentation,
30
    InvalidIntegerPrefix,
31
    InvalidTableIndex,
32
    InvalidHuffmanCode,
33
    InvalidUtf8,
34
    InvalidStatusCode,
35
    InvalidPseudoheader,
36
    InvalidMaxDynamicSize,
37
    IntegerOverflow,
38
    NeedMore(NeedMore),
39
}
40
41
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
42
pub enum NeedMore {
43
    UnexpectedEndOfStream,
44
    IntegerUnderflow,
45
    StringUnderflow,
46
}
47
48
enum Representation {
49
    /// Indexed header field representation
50
    ///
51
    /// An indexed header field representation identifies an entry in either the
52
    /// static table or the dynamic table (see Section 2.3).
53
    ///
54
    /// # Header encoding
55
    ///
56
    /// ```text
57
    ///   0   1   2   3   4   5   6   7
58
    /// +---+---+---+---+---+---+---+---+
59
    /// | 1 |        Index (7+)         |
60
    /// +---+---------------------------+
61
    /// ```
62
    Indexed,
63
64
    /// Literal Header Field with Incremental Indexing
65
    ///
66
    /// A literal header field with incremental indexing representation results
67
    /// in appending a header field to the decoded header list and inserting it
68
    /// as a new entry into the dynamic table.
69
    ///
70
    /// # Header encoding
71
    ///
72
    /// ```text
73
    ///   0   1   2   3   4   5   6   7
74
    /// +---+---+---+---+---+---+---+---+
75
    /// | 0 | 1 |      Index (6+)       |
76
    /// +---+---+-----------------------+
77
    /// | H |     Value Length (7+)     |
78
    /// +---+---------------------------+
79
    /// | Value String (Length octets)  |
80
    /// +-------------------------------+
81
    /// ```
82
    LiteralWithIndexing,
83
84
    /// Literal Header Field without Indexing
85
    ///
86
    /// A literal header field without indexing representation results in
87
    /// appending a header field to the decoded header list without altering the
88
    /// dynamic table.
89
    ///
90
    /// # Header encoding
91
    ///
92
    /// ```text
93
    ///   0   1   2   3   4   5   6   7
94
    /// +---+---+---+---+---+---+---+---+
95
    /// | 0 | 0 | 0 | 0 |  Index (4+)   |
96
    /// +---+---+-----------------------+
97
    /// | H |     Value Length (7+)     |
98
    /// +---+---------------------------+
99
    /// | Value String (Length octets)  |
100
    /// +-------------------------------+
101
    /// ```
102
    LiteralWithoutIndexing,
103
104
    /// Literal Header Field Never Indexed
105
    ///
106
    /// A literal header field never-indexed representation results in appending
107
    /// a header field to the decoded header list without altering the dynamic
108
    /// table. Intermediaries MUST use the same representation for encoding this
109
    /// header field.
110
    ///
111
    /// ```text
112
    ///   0   1   2   3   4   5   6   7
113
    /// +---+---+---+---+---+---+---+---+
114
    /// | 0 | 0 | 0 | 1 |  Index (4+)   |
115
    /// +---+---+-----------------------+
116
    /// | H |     Value Length (7+)     |
117
    /// +---+---------------------------+
118
    /// | Value String (Length octets)  |
119
    /// +-------------------------------+
120
    /// ```
121
    LiteralNeverIndexed,
122
123
    /// Dynamic Table Size Update
124
    ///
125
    /// A dynamic table size update signals a change to the size of the dynamic
126
    /// table.
127
    ///
128
    /// # Header encoding
129
    ///
130
    /// ```text
131
    ///   0   1   2   3   4   5   6   7
132
    /// +---+---+---+---+---+---+---+---+
133
    /// | 0 | 0 | 1 |   Max size (5+)   |
134
    /// +---+---------------------------+
135
    /// ```
136
    SizeUpdate,
137
}
138
139
#[derive(Debug)]
140
struct Table {
141
    entries: VecDeque<Header>,
142
    size: usize,
143
    max_size: usize,
144
}
145
146
struct StringMarker {
147
    offset: usize,
148
    len: usize,
149
    string: Option<Bytes>,
150
}
151
152
// ===== impl Decoder =====
153
154
impl Decoder {
155
    /// Creates a new `Decoder` with all settings set to default values.
156
28.2k
    pub fn new(size: usize) -> Decoder {
157
28.2k
        Decoder {
158
28.2k
            max_size_update: None,
159
28.2k
            last_max_update: size,
160
28.2k
            table: Table::new(size),
161
28.2k
            buffer: BytesMut::with_capacity(4096),
162
28.2k
        }
163
28.2k
    }
164
165
    /// Queues a potential size update
166
    #[allow(dead_code)]
167
0
    pub fn queue_size_update(&mut self, size: usize) {
168
0
        let size = match self.max_size_update {
169
0
            Some(v) => cmp::max(v, size),
170
0
            None => size,
171
        };
172
173
0
        self.max_size_update = Some(size);
174
0
    }
175
176
    /// Decodes the headers found in the given buffer.
177
69.7k
    pub fn decode<F>(
178
69.7k
        &mut self,
179
69.7k
        src: &mut Cursor<&mut BytesMut>,
180
69.7k
        mut f: F,
181
69.7k
    ) -> Result<(), DecoderError>
182
69.7k
    where
183
69.7k
        F: FnMut(Header) -> ControlFlow<()>,
184
    {
185
        use self::Representation::*;
186
187
69.7k
        let mut can_resize = true;
188
189
69.7k
        if let Some(size) = self.max_size_update.take() {
190
0
            self.last_max_update = size;
191
69.7k
        }
192
193
69.7k
        let span = tracing::trace_span!("hpack::decode");
194
69.7k
        let _e = span.enter();
195
196
69.7k
        tracing::trace!("decode");
197
198
13.4M
        while let Some(ty) = peek_u8(src) {
199
            // At this point we are always at the beginning of the next block
200
            // within the HPACK data. The type of the block can always be
201
            // determined from the first byte.
202
13.3M
            match Representation::load(ty)? {
203
                Indexed => {
204
10.5M
                    tracing::trace!(rem = src.remaining(), kind = %"Indexed");
205
10.5M
                    can_resize = false;
206
10.5M
                    let entry = self.decode_indexed(src)?;
207
10.5M
                    consume(src);
208
10.5M
                    if f(entry).is_break() {
209
0
                        break;
210
10.5M
                    }
211
                }
212
                LiteralWithIndexing => {
213
1.18M
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithIndexing");
214
1.18M
                    can_resize = false;
215
1.18M
                    let entry = self.decode_literal(src, true)?;
216
217
                    // Insert the header into the table
218
1.17M
                    self.table.insert(entry.clone());
219
1.17M
                    consume(src);
220
221
1.17M
                    if f(entry).is_break() {
222
0
                        break;
223
1.17M
                    }
224
                }
225
                LiteralWithoutIndexing => {
226
1.41M
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithoutIndexing");
227
1.41M
                    can_resize = false;
228
1.41M
                    let entry = self.decode_literal(src, false)?;
229
1.40M
                    consume(src);
230
1.40M
                    if f(entry).is_break() {
231
0
                        break;
232
1.40M
                    }
233
                }
234
                LiteralNeverIndexed => {
235
272k
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralNeverIndexed");
236
272k
                    can_resize = false;
237
272k
                    let entry = self.decode_literal(src, false)?;
238
270k
                    consume(src);
239
240
                    // TODO: Track that this should never be indexed
241
242
270k
                    if f(entry).is_break() {
243
0
                        break;
244
270k
                    }
245
                }
246
                SizeUpdate => {
247
12.2k
                    tracing::trace!(rem = src.remaining(), kind = %"SizeUpdate");
248
12.2k
                    if !can_resize {
249
503
                        return Err(DecoderError::InvalidMaxDynamicSize);
250
11.7k
                    }
251
252
                    // Handle the dynamic table size update
253
11.7k
                    self.process_size_update(src)?;
254
10.7k
                    consume(src);
255
                }
256
            }
257
        }
258
259
49.9k
        Ok(())
260
69.7k
    }
<h2::hpack::decoder::Decoder>::decode::<<h2::frame::headers::HeaderBlock>::load::{closure#0}>
Line
Count
Source
177
55.2k
    pub fn decode<F>(
178
55.2k
        &mut self,
179
55.2k
        src: &mut Cursor<&mut BytesMut>,
180
55.2k
        mut f: F,
181
55.2k
    ) -> Result<(), DecoderError>
182
55.2k
    where
183
55.2k
        F: FnMut(Header) -> ControlFlow<()>,
184
    {
185
        use self::Representation::*;
186
187
55.2k
        let mut can_resize = true;
188
189
55.2k
        if let Some(size) = self.max_size_update.take() {
190
0
            self.last_max_update = size;
191
55.2k
        }
192
193
55.2k
        let span = tracing::trace_span!("hpack::decode");
194
55.2k
        let _e = span.enter();
195
196
55.2k
        tracing::trace!("decode");
197
198
859k
        while let Some(ty) = peek_u8(src) {
199
            // At this point we are always at the beginning of the next block
200
            // within the HPACK data. The type of the block can always be
201
            // determined from the first byte.
202
817k
            match Representation::load(ty)? {
203
                Indexed => {
204
669k
                    tracing::trace!(rem = src.remaining(), kind = %"Indexed");
205
669k
                    can_resize = false;
206
669k
                    let entry = self.decode_indexed(src)?;
207
668k
                    consume(src);
208
668k
                    if f(entry).is_break() {
209
0
                        break;
210
668k
                    }
211
                }
212
                LiteralWithIndexing => {
213
106k
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithIndexing");
214
106k
                    can_resize = false;
215
106k
                    let entry = self.decode_literal(src, true)?;
216
217
                    // Insert the header into the table
218
101k
                    self.table.insert(entry.clone());
219
101k
                    consume(src);
220
221
101k
                    if f(entry).is_break() {
222
0
                        break;
223
101k
                    }
224
                }
225
                LiteralWithoutIndexing => {
226
30.1k
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithoutIndexing");
227
30.1k
                    can_resize = false;
228
30.1k
                    let entry = self.decode_literal(src, false)?;
229
24.5k
                    consume(src);
230
24.5k
                    if f(entry).is_break() {
231
0
                        break;
232
24.5k
                    }
233
                }
234
                LiteralNeverIndexed => {
235
2.61k
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralNeverIndexed");
236
2.61k
                    can_resize = false;
237
2.61k
                    let entry = self.decode_literal(src, false)?;
238
1.37k
                    consume(src);
239
240
                    // TODO: Track that this should never be indexed
241
242
1.37k
                    if f(entry).is_break() {
243
0
                        break;
244
1.37k
                    }
245
                }
246
                SizeUpdate => {
247
9.41k
                    tracing::trace!(rem = src.remaining(), kind = %"SizeUpdate");
248
9.41k
                    if !can_resize {
249
340
                        return Err(DecoderError::InvalidMaxDynamicSize);
250
9.07k
                    }
251
252
                    // Handle the dynamic table size update
253
9.07k
                    self.process_size_update(src)?;
254
8.43k
                    consume(src);
255
                }
256
            }
257
        }
258
259
41.7k
        Ok(())
260
55.2k
    }
<h2::hpack::decoder::Decoder>::decode::<h2::fuzz_bridge::fuzz_logic::fuzz_hpack::{closure#0}>
Line
Count
Source
177
14.5k
    pub fn decode<F>(
178
14.5k
        &mut self,
179
14.5k
        src: &mut Cursor<&mut BytesMut>,
180
14.5k
        mut f: F,
181
14.5k
    ) -> Result<(), DecoderError>
182
14.5k
    where
183
14.5k
        F: FnMut(Header) -> ControlFlow<()>,
184
    {
185
        use self::Representation::*;
186
187
14.5k
        let mut can_resize = true;
188
189
14.5k
        if let Some(size) = self.max_size_update.take() {
190
0
            self.last_max_update = size;
191
14.5k
        }
192
193
14.5k
        let span = tracing::trace_span!("hpack::decode");
194
14.5k
        let _e = span.enter();
195
196
14.5k
        tracing::trace!("decode");
197
198
12.5M
        while let Some(ty) = peek_u8(src) {
199
            // At this point we are always at the beginning of the next block
200
            // within the HPACK data. The type of the block can always be
201
            // determined from the first byte.
202
12.5M
            match Representation::load(ty)? {
203
                Indexed => {
204
9.84M
                    tracing::trace!(rem = src.remaining(), kind = %"Indexed");
205
9.84M
                    can_resize = false;
206
9.84M
                    let entry = self.decode_indexed(src)?;
207
9.84M
                    consume(src);
208
9.84M
                    if f(entry).is_break() {
209
0
                        break;
210
9.84M
                    }
211
                }
212
                LiteralWithIndexing => {
213
1.07M
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithIndexing");
214
1.07M
                    can_resize = false;
215
1.07M
                    let entry = self.decode_literal(src, true)?;
216
217
                    // Insert the header into the table
218
1.07M
                    self.table.insert(entry.clone());
219
1.07M
                    consume(src);
220
221
1.07M
                    if f(entry).is_break() {
222
0
                        break;
223
1.07M
                    }
224
                }
225
                LiteralWithoutIndexing => {
226
1.38M
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithoutIndexing");
227
1.38M
                    can_resize = false;
228
1.38M
                    let entry = self.decode_literal(src, false)?;
229
1.37M
                    consume(src);
230
1.37M
                    if f(entry).is_break() {
231
0
                        break;
232
1.37M
                    }
233
                }
234
                LiteralNeverIndexed => {
235
270k
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralNeverIndexed");
236
270k
                    can_resize = false;
237
270k
                    let entry = self.decode_literal(src, false)?;
238
269k
                    consume(src);
239
240
                    // TODO: Track that this should never be indexed
241
242
269k
                    if f(entry).is_break() {
243
0
                        break;
244
269k
                    }
245
                }
246
                SizeUpdate => {
247
2.79k
                    tracing::trace!(rem = src.remaining(), kind = %"SizeUpdate");
248
2.79k
                    if !can_resize {
249
163
                        return Err(DecoderError::InvalidMaxDynamicSize);
250
2.63k
                    }
251
252
                    // Handle the dynamic table size update
253
2.63k
                    self.process_size_update(src)?;
254
2.35k
                    consume(src);
255
                }
256
            }
257
        }
258
259
8.21k
        Ok(())
260
14.5k
    }
261
262
11.7k
    fn process_size_update(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<(), DecoderError> {
263
11.7k
        let new_size = decode_int(buf, 5)?;
264
265
11.0k
        if new_size > self.last_max_update {
266
236
            return Err(DecoderError::InvalidMaxDynamicSize);
267
10.7k
        }
268
269
10.7k
        tracing::debug!(
270
0
            from = self.table.size(),
271
            to = new_size,
272
0
            "Decoder changed max table size"
273
        );
274
275
10.7k
        self.table.set_max_size(new_size);
276
277
10.7k
        Ok(())
278
11.7k
    }
279
280
10.5M
    fn decode_indexed(&self, buf: &mut Cursor<&mut BytesMut>) -> Result<Header, DecoderError> {
281
10.5M
        let index = decode_int(buf, 7)?;
282
10.5M
        self.table.get(index)
283
10.5M
    }
284
285
2.87M
    fn decode_literal(
286
2.87M
        &mut self,
287
2.87M
        buf: &mut Cursor<&mut BytesMut>,
288
2.87M
        index: bool,
289
2.87M
    ) -> Result<Header, DecoderError> {
290
2.87M
        let prefix = if index { 6 } else { 4 };
291
292
        // Extract the table index for the name, or 0 if not indexed
293
2.87M
        let table_idx = decode_int(buf, prefix)?;
294
295
        // First, read the header name
296
2.86M
        if table_idx == 0 {
297
954k
            let old_pos = buf.position();
298
954k
            let name_marker = self.try_decode_string(buf)?;
299
952k
            let value_marker = self.try_decode_string(buf)?;
300
950k
            buf.set_position(old_pos);
301
            // Read the name as a literal
302
950k
            let name = name_marker.consume(buf);
303
950k
            let value = value_marker.consume(buf);
304
950k
            Header::new(name, value)
305
        } else {
306
1.91M
            let e = self.table.get(table_idx)?;
307
1.91M
            let value = self.decode_string(buf)?;
308
309
1.91M
            e.name().into_entry(value)
310
        }
311
2.87M
    }
312
313
3.82M
    fn try_decode_string(
314
3.82M
        &mut self,
315
3.82M
        buf: &mut Cursor<&mut BytesMut>,
316
3.82M
    ) -> Result<StringMarker, DecoderError> {
317
3.82M
        let old_pos = buf.position();
318
        const HUFF_FLAG: u8 = 0b1000_0000;
319
320
        // The first bit in the first byte contains the huffman encoded flag.
321
3.82M
        let huff = match peek_u8(buf) {
322
3.82M
            Some(hdr) => (hdr & HUFF_FLAG) == HUFF_FLAG,
323
1.51k
            None => return Err(DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream)),
324
        };
325
326
        // Decode the string length using 7 bit prefix
327
3.82M
        let len = decode_int(buf, 7)?;
328
329
3.81M
        if len > buf.remaining() {
330
5.45k
            tracing::trace!(len, remaining = buf.remaining(), "decode_string underflow",);
331
5.45k
            return Err(DecoderError::NeedMore(NeedMore::StringUnderflow));
332
3.81M
        }
333
334
3.81M
        let offset = (buf.position() - old_pos) as usize;
335
3.81M
        if huff {
336
2.83M
            let ret = {
337
2.83M
                let raw = &buf.chunk()[..len];
338
2.83M
                huffman::decode(raw, &mut self.buffer).map(|buf| StringMarker {
339
2.83M
                    offset,
340
2.83M
                    len,
341
2.83M
                    string: Some(BytesMut::freeze(buf)),
342
2.83M
                })
343
            };
344
345
2.83M
            buf.advance(len);
346
2.83M
            ret
347
        } else {
348
981k
            buf.advance(len);
349
981k
            Ok(StringMarker {
350
981k
                offset,
351
981k
                len,
352
981k
                string: None,
353
981k
            })
354
        }
355
3.82M
    }
356
357
1.91M
    fn decode_string(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<Bytes, DecoderError> {
358
1.91M
        let old_pos = buf.position();
359
1.91M
        let marker = self.try_decode_string(buf)?;
360
1.91M
        buf.set_position(old_pos);
361
1.91M
        Ok(marker.consume(buf))
362
1.91M
    }
363
}
364
365
impl Default for Decoder {
366
0
    fn default() -> Decoder {
367
0
        Decoder::new(4096)
368
0
    }
369
}
370
371
// ===== impl Representation =====
372
373
impl Representation {
374
13.3M
    pub fn load(byte: u8) -> Result<Representation, DecoderError> {
375
        const INDEXED: u8 = 0b1000_0000;
376
        const LITERAL_WITH_INDEXING: u8 = 0b0100_0000;
377
        const LITERAL_WITHOUT_INDEXING: u8 = 0b1111_0000;
378
        const LITERAL_NEVER_INDEXED: u8 = 0b0001_0000;
379
        const SIZE_UPDATE_MASK: u8 = 0b1110_0000;
380
        const SIZE_UPDATE: u8 = 0b0010_0000;
381
382
        // TODO: What did I even write here?
383
384
13.3M
        if byte & INDEXED == INDEXED {
385
10.5M
            Ok(Representation::Indexed)
386
2.88M
        } else if byte & LITERAL_WITH_INDEXING == LITERAL_WITH_INDEXING {
387
1.18M
            Ok(Representation::LiteralWithIndexing)
388
1.69M
        } else if byte & LITERAL_WITHOUT_INDEXING == 0 {
389
1.41M
            Ok(Representation::LiteralWithoutIndexing)
390
284k
        } else if byte & LITERAL_WITHOUT_INDEXING == LITERAL_NEVER_INDEXED {
391
272k
            Ok(Representation::LiteralNeverIndexed)
392
12.2k
        } else if byte & SIZE_UPDATE_MASK == SIZE_UPDATE {
393
12.2k
            Ok(Representation::SizeUpdate)
394
        } else {
395
0
            Err(DecoderError::InvalidRepresentation)
396
        }
397
13.3M
    }
398
}
399
400
17.2M
fn decode_int<B: Buf>(buf: &mut B, prefix_size: u8) -> Result<usize, DecoderError> {
401
    // The octet limit is chosen such that the maximum allowed *value* can
402
    // never overflow an unsigned 32-bit integer. The maximum value of any
403
    // integer that can be encoded with 5 octets is ~2^28
404
    const MAX_BYTES: usize = 5;
405
    const VARINT_MASK: u8 = 0b0111_1111;
406
    const VARINT_FLAG: u8 = 0b1000_0000;
407
408
17.2M
    if prefix_size < 1 || prefix_size > 8 {
409
0
        return Err(DecoderError::InvalidIntegerPrefix);
410
17.2M
    }
411
412
17.2M
    if !buf.has_remaining() {
413
0
        return Err(DecoderError::NeedMore(NeedMore::IntegerUnderflow));
414
17.2M
    }
415
416
17.2M
    let mask = if prefix_size == 8 {
417
0
        0xFF
418
    } else {
419
17.2M
        (1u8 << prefix_size).wrapping_sub(1)
420
    };
421
422
17.2M
    let mut ret = (buf.get_u8() & mask) as usize;
423
424
17.2M
    if ret < mask as usize {
425
        // Value fits in the prefix bits
426
17.1M
        return Ok(ret);
427
26.5k
    }
428
429
    // The int did not fit in the prefix bits, so continue reading.
430
    //
431
    // The total number of bytes used to represent the int. The first byte was
432
    // the prefix, so start at 1.
433
26.5k
    let mut bytes = 1;
434
435
    // The rest of the int is stored as a varint -- 7 bits for the value and 1
436
    // bit to indicate if it is the last byte.
437
26.5k
    let mut shift = 0;
438
439
52.0k
    while buf.has_remaining() {
440
49.7k
        let b = buf.get_u8();
441
442
49.7k
        bytes += 1;
443
49.7k
        ret += ((b & VARINT_MASK) as usize) << shift;
444
49.7k
        shift += 7;
445
446
49.7k
        if b & VARINT_FLAG == 0 {
447
23.7k
            return Ok(ret);
448
25.9k
        }
449
450
25.9k
        if bytes == MAX_BYTES {
451
            // The spec requires that this situation is an error
452
419
            return Err(DecoderError::IntegerOverflow);
453
25.5k
        }
454
    }
455
456
2.32k
    Err(DecoderError::NeedMore(NeedMore::IntegerUnderflow))
457
17.2M
}
458
459
17.2M
fn peek_u8<B: Buf>(buf: &B) -> Option<u8> {
460
17.2M
    if buf.has_remaining() {
461
17.2M
        Some(buf.chunk()[0])
462
    } else {
463
51.4k
        None
464
    }
465
17.2M
}
466
467
14.3M
fn take(buf: &mut Cursor<&mut BytesMut>, n: usize) -> Bytes {
468
14.3M
    let pos = buf.position() as usize;
469
14.3M
    let mut head = buf.get_mut().split_to(pos + n);
470
14.3M
    buf.set_position(0);
471
14.3M
    head.advance(pos);
472
14.3M
    head.freeze()
473
14.3M
}
474
475
impl StringMarker {
476
3.81M
    fn consume(self, buf: &mut Cursor<&mut BytesMut>) -> Bytes {
477
3.81M
        buf.advance(self.offset);
478
3.81M
        match self.string {
479
2.83M
            Some(string) => {
480
2.83M
                buf.advance(self.len);
481
2.83M
                string
482
            }
483
980k
            None => take(buf, self.len),
484
        }
485
3.81M
    }
486
}
487
488
13.3M
fn consume(buf: &mut Cursor<&mut BytesMut>) {
489
    // remove bytes from the internal BytesMut when they have been successfully
490
    // decoded. This is a more permanent cursor position, which will be
491
    // used to resume if decoding was only partial.
492
13.3M
    take(buf, 0);
493
13.3M
}
494
495
// ===== impl Table =====
496
497
impl Table {
498
28.2k
    fn new(max_size: usize) -> Table {
499
28.2k
        Table {
500
28.2k
            entries: VecDeque::new(),
501
28.2k
            size: 0,
502
28.2k
            max_size,
503
28.2k
        }
504
28.2k
    }
505
506
0
    fn size(&self) -> usize {
507
0
        self.size
508
0
    }
509
510
    /// Returns the entry located at the given index.
511
    ///
512
    /// The table is 1-indexed and constructed in such a way that the first
513
    /// entries belong to the static table, followed by entries in the dynamic
514
    /// table. They are merged into a single index address space, though.
515
    ///
516
    /// This is according to the [HPACK spec, section 2.3.3.]
517
    /// (http://http2.github.io/http2-spec/compression.html#index.address.space)
518
12.4M
    pub fn get(&self, index: usize) -> Result<Header, DecoderError> {
519
12.4M
        if index == 0 {
520
41
            return Err(DecoderError::InvalidTableIndex);
521
12.4M
        }
522
523
12.4M
        if index <= 61 {
524
12.3M
            return Ok(get_static(index));
525
102k
        }
526
527
        // Convert the index for lookup in the entries structure.
528
102k
        match self.entries.get(index - 62) {
529
101k
            Some(e) => Ok(e.clone()),
530
830
            None => Err(DecoderError::InvalidTableIndex),
531
        }
532
12.4M
    }
533
534
1.17M
    fn insert(&mut self, entry: Header) {
535
1.17M
        let len = entry.len();
536
537
1.17M
        self.reserve(len);
538
539
1.17M
        if self.size + len <= self.max_size {
540
94.6k
            self.size += len;
541
94.6k
542
94.6k
            // Track the entry
543
94.6k
            self.entries.push_front(entry);
544
1.08M
        }
545
1.17M
    }
546
547
10.7k
    fn set_max_size(&mut self, size: usize) {
548
10.7k
        self.max_size = size;
549
        // Make the table size fit within the new constraints.
550
10.7k
        self.consolidate();
551
10.7k
    }
552
553
1.17M
    fn reserve(&mut self, size: usize) {
554
1.20M
        while self.size + size > self.max_size {
555
1.11M
            match self.entries.pop_back() {
556
30.1k
                Some(last) => {
557
30.1k
                    self.size -= last.len();
558
30.1k
                }
559
1.08M
                None => return,
560
            }
561
        }
562
1.17M
    }
563
564
10.7k
    fn consolidate(&mut self) {
565
16.2k
        while self.size > self.max_size {
566
            {
567
5.46k
                let last = match self.entries.back() {
568
5.46k
                    Some(x) => x,
569
                    None => {
570
                        // Can never happen as the size of the table must reach
571
                        // 0 by the time we've exhausted all elements.
572
0
                        panic!("Size of table != 0, but no headers left!");
573
                    }
574
                };
575
576
5.46k
                self.size -= last.len();
577
            }
578
579
5.46k
            self.entries.pop_back();
580
        }
581
10.7k
    }
582
}
583
584
// ===== impl DecoderError =====
585
586
impl From<Utf8Error> for DecoderError {
587
43
    fn from(_: Utf8Error) -> DecoderError {
588
        // TODO: Better error?
589
43
        DecoderError::InvalidUtf8
590
43
    }
591
}
592
593
impl From<header::InvalidHeaderValue> for DecoderError {
594
375
    fn from(_: header::InvalidHeaderValue) -> DecoderError {
595
        // TODO: Better error?
596
375
        DecoderError::InvalidUtf8
597
375
    }
598
}
599
600
impl From<header::InvalidHeaderName> for DecoderError {
601
4.07k
    fn from(_: header::InvalidHeaderName) -> DecoderError {
602
        // TODO: Better error
603
4.07k
        DecoderError::InvalidUtf8
604
4.07k
    }
605
}
606
607
impl From<method::InvalidMethod> for DecoderError {
608
391
    fn from(_: method::InvalidMethod) -> DecoderError {
609
        // TODO: Better error
610
391
        DecoderError::InvalidUtf8
611
391
    }
612
}
613
614
impl From<status::InvalidStatusCode> for DecoderError {
615
6
    fn from(_: status::InvalidStatusCode) -> DecoderError {
616
        // TODO: Better error
617
6
        DecoderError::InvalidUtf8
618
6
    }
619
}
620
621
impl From<DecoderError> for frame::Error {
622
13.5k
    fn from(src: DecoderError) -> Self {
623
13.5k
        frame::Error::Hpack(src)
624
13.5k
    }
625
}
626
627
/// Get an entry from the static table
628
12.3M
pub fn get_static(idx: usize) -> Header {
629
    use http::header::HeaderValue;
630
631
12.3M
    match idx {
632
126k
        1 => Header::Authority(BytesStr::from_static("")),
633
657k
        2 => Header::Method(Method::GET),
634
1.11M
        3 => Header::Method(Method::POST),
635
2.03M
        4 => Header::Path(BytesStr::from_static("/")),
636
33.8k
        5 => Header::Path(BytesStr::from_static("/index.html")),
637
72.5k
        6 => Header::Scheme(BytesStr::from_static("http")),
638
115k
        7 => Header::Scheme(BytesStr::from_static("https")),
639
1.17M
        8 => Header::Status(StatusCode::OK),
640
143k
        9 => Header::Status(StatusCode::NO_CONTENT),
641
37.0k
        10 => Header::Status(StatusCode::PARTIAL_CONTENT),
642
47.8k
        11 => Header::Status(StatusCode::NOT_MODIFIED),
643
85.5k
        12 => Header::Status(StatusCode::BAD_REQUEST),
644
24.5k
        13 => Header::Status(StatusCode::NOT_FOUND),
645
454k
        14 => Header::Status(StatusCode::INTERNAL_SERVER_ERROR),
646
1.25M
        15 => Header::Field {
647
1.25M
            name: header::ACCEPT_CHARSET,
648
1.25M
            value: HeaderValue::from_static(""),
649
1.25M
        },
650
145k
        16 => Header::Field {
651
145k
            name: header::ACCEPT_ENCODING,
652
145k
            value: HeaderValue::from_static("gzip, deflate"),
653
145k
        },
654
138k
        17 => Header::Field {
655
138k
            name: header::ACCEPT_LANGUAGE,
656
138k
            value: HeaderValue::from_static(""),
657
138k
        },
658
152k
        18 => Header::Field {
659
152k
            name: header::ACCEPT_RANGES,
660
152k
            value: HeaderValue::from_static(""),
661
152k
        },
662
93.1k
        19 => Header::Field {
663
93.1k
            name: header::ACCEPT,
664
93.1k
            value: HeaderValue::from_static(""),
665
93.1k
        },
666
126k
        20 => Header::Field {
667
126k
            name: header::ACCESS_CONTROL_ALLOW_ORIGIN,
668
126k
            value: HeaderValue::from_static(""),
669
126k
        },
670
177k
        21 => Header::Field {
671
177k
            name: header::AGE,
672
177k
            value: HeaderValue::from_static(""),
673
177k
        },
674
51.2k
        22 => Header::Field {
675
51.2k
            name: header::ALLOW,
676
51.2k
            value: HeaderValue::from_static(""),
677
51.2k
        },
678
329k
        23 => Header::Field {
679
329k
            name: header::AUTHORIZATION,
680
329k
            value: HeaderValue::from_static(""),
681
329k
        },
682
27.9k
        24 => Header::Field {
683
27.9k
            name: header::CACHE_CONTROL,
684
27.9k
            value: HeaderValue::from_static(""),
685
27.9k
        },
686
121k
        25 => Header::Field {
687
121k
            name: header::CONTENT_DISPOSITION,
688
121k
            value: HeaderValue::from_static(""),
689
121k
        },
690
31.1k
        26 => Header::Field {
691
31.1k
            name: header::CONTENT_ENCODING,
692
31.1k
            value: HeaderValue::from_static(""),
693
31.1k
        },
694
228k
        27 => Header::Field {
695
228k
            name: header::CONTENT_LANGUAGE,
696
228k
            value: HeaderValue::from_static(""),
697
228k
        },
698
35.6k
        28 => Header::Field {
699
35.6k
            name: header::CONTENT_LENGTH,
700
35.6k
            value: HeaderValue::from_static(""),
701
35.6k
        },
702
79.7k
        29 => Header::Field {
703
79.7k
            name: header::CONTENT_LOCATION,
704
79.7k
            value: HeaderValue::from_static(""),
705
79.7k
        },
706
27.4k
        30 => Header::Field {
707
27.4k
            name: header::CONTENT_RANGE,
708
27.4k
            value: HeaderValue::from_static(""),
709
27.4k
        },
710
604k
        31 => Header::Field {
711
604k
            name: header::CONTENT_TYPE,
712
604k
            value: HeaderValue::from_static(""),
713
604k
        },
714
655k
        32 => Header::Field {
715
655k
            name: header::COOKIE,
716
655k
            value: HeaderValue::from_static(""),
717
655k
        },
718
33.0k
        33 => Header::Field {
719
33.0k
            name: header::DATE,
720
33.0k
            value: HeaderValue::from_static(""),
721
33.0k
        },
722
28.2k
        34 => Header::Field {
723
28.2k
            name: header::ETAG,
724
28.2k
            value: HeaderValue::from_static(""),
725
28.2k
        },
726
123k
        35 => Header::Field {
727
123k
            name: header::EXPECT,
728
123k
            value: HeaderValue::from_static(""),
729
123k
        },
730
119k
        36 => Header::Field {
731
119k
            name: header::EXPIRES,
732
119k
            value: HeaderValue::from_static(""),
733
119k
        },
734
34.6k
        37 => Header::Field {
735
34.6k
            name: header::FROM,
736
34.6k
            value: HeaderValue::from_static(""),
737
34.6k
        },
738
40.3k
        38 => Header::Field {
739
40.3k
            name: header::HOST,
740
40.3k
            value: HeaderValue::from_static(""),
741
40.3k
        },
742
136k
        39 => Header::Field {
743
136k
            name: header::IF_MATCH,
744
136k
            value: HeaderValue::from_static(""),
745
136k
        },
746
55.8k
        40 => Header::Field {
747
55.8k
            name: header::IF_MODIFIED_SINCE,
748
55.8k
            value: HeaderValue::from_static(""),
749
55.8k
        },
750
136k
        41 => Header::Field {
751
136k
            name: header::IF_NONE_MATCH,
752
136k
            value: HeaderValue::from_static(""),
753
136k
        },
754
31.1k
        42 => Header::Field {
755
31.1k
            name: header::IF_RANGE,
756
31.1k
            value: HeaderValue::from_static(""),
757
31.1k
        },
758
30.4k
        43 => Header::Field {
759
30.4k
            name: header::IF_UNMODIFIED_SINCE,
760
30.4k
            value: HeaderValue::from_static(""),
761
30.4k
        },
762
112k
        44 => Header::Field {
763
112k
            name: header::LAST_MODIFIED,
764
112k
            value: HeaderValue::from_static(""),
765
112k
        },
766
36.1k
        45 => Header::Field {
767
36.1k
            name: header::LINK,
768
36.1k
            value: HeaderValue::from_static(""),
769
36.1k
        },
770
199k
        46 => Header::Field {
771
199k
            name: header::LOCATION,
772
199k
            value: HeaderValue::from_static(""),
773
199k
        },
774
48.2k
        47 => Header::Field {
775
48.2k
            name: header::MAX_FORWARDS,
776
48.2k
            value: HeaderValue::from_static(""),
777
48.2k
        },
778
28.8k
        48 => Header::Field {
779
28.8k
            name: header::PROXY_AUTHENTICATE,
780
28.8k
            value: HeaderValue::from_static(""),
781
28.8k
        },
782
34.9k
        49 => Header::Field {
783
34.9k
            name: header::PROXY_AUTHORIZATION,
784
34.9k
            value: HeaderValue::from_static(""),
785
34.9k
        },
786
43.1k
        50 => Header::Field {
787
43.1k
            name: header::RANGE,
788
43.1k
            value: HeaderValue::from_static(""),
789
43.1k
        },
790
199k
        51 => Header::Field {
791
199k
            name: header::REFERER,
792
199k
            value: HeaderValue::from_static(""),
793
199k
        },
794
44.6k
        52 => Header::Field {
795
44.6k
            name: header::REFRESH,
796
44.6k
            value: HeaderValue::from_static(""),
797
44.6k
        },
798
117k
        53 => Header::Field {
799
117k
            name: header::RETRY_AFTER,
800
117k
            value: HeaderValue::from_static(""),
801
117k
        },
802
15.1k
        54 => Header::Field {
803
15.1k
            name: header::SERVER,
804
15.1k
            value: HeaderValue::from_static(""),
805
15.1k
        },
806
26.1k
        55 => Header::Field {
807
26.1k
            name: header::SET_COOKIE,
808
26.1k
            value: HeaderValue::from_static(""),
809
26.1k
        },
810
70.5k
        56 => Header::Field {
811
70.5k
            name: header::STRICT_TRANSPORT_SECURITY,
812
70.5k
            value: HeaderValue::from_static(""),
813
70.5k
        },
814
30.5k
        57 => Header::Field {
815
30.5k
            name: header::TRANSFER_ENCODING,
816
30.5k
            value: HeaderValue::from_static(""),
817
30.5k
        },
818
47.8k
        58 => Header::Field {
819
47.8k
            name: header::USER_AGENT,
820
47.8k
            value: HeaderValue::from_static(""),
821
47.8k
        },
822
30.8k
        59 => Header::Field {
823
30.8k
            name: header::VARY,
824
30.8k
            value: HeaderValue::from_static(""),
825
30.8k
        },
826
33.4k
        60 => Header::Field {
827
33.4k
            name: header::VIA,
828
33.4k
            value: HeaderValue::from_static(""),
829
33.4k
        },
830
30.9k
        61 => Header::Field {
831
30.9k
            name: header::WWW_AUTHENTICATE,
832
30.9k
            value: HeaderValue::from_static(""),
833
30.9k
        },
834
0
        _ => unreachable!(),
835
    }
836
12.3M
}
837
838
#[cfg(test)]
839
mod test {
840
    use super::*;
841
842
    #[test]
843
    fn test_peek_u8() {
844
        let b = 0xff;
845
        let mut buf = Cursor::new(vec![b]);
846
        assert_eq!(peek_u8(&buf), Some(b));
847
        assert_eq!(buf.get_u8(), b);
848
        assert_eq!(peek_u8(&buf), None);
849
    }
850
851
    #[test]
852
    fn test_decode_string_empty() {
853
        let mut de = Decoder::new(0);
854
        let mut buf = BytesMut::new();
855
        let err = de.decode_string(&mut Cursor::new(&mut buf)).unwrap_err();
856
        assert_eq!(err, DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream));
857
    }
858
859
    #[test]
860
    fn test_decode_empty() {
861
        let mut de = Decoder::new(0);
862
        let mut buf = BytesMut::new();
863
        de.decode(&mut Cursor::new(&mut buf), |_| ControlFlow::Continue(()))
864
            .unwrap();
865
    }
866
867
    #[test]
868
    fn test_decode_indexed_larger_than_table() {
869
        let mut de = Decoder::new(0);
870
871
        let mut buf = BytesMut::new();
872
        buf.extend([0b01000000, 0x80 | 2]);
873
        buf.extend(huff_encode(b"foo"));
874
        buf.extend([0x80 | 3]);
875
        buf.extend(huff_encode(b"bar"));
876
877
        let mut res = vec![];
878
        de.decode(&mut Cursor::new(&mut buf), |h| {
879
            res.push(h);
880
            ControlFlow::Continue(())
881
        })
882
        .unwrap();
883
884
        assert_eq!(res.len(), 1);
885
        assert_eq!(de.table.size(), 0);
886
887
        match res[0] {
888
            Header::Field {
889
                ref name,
890
                ref value,
891
            } => {
892
                assert_eq!(name, "foo");
893
                assert_eq!(value, "bar");
894
            }
895
            _ => panic!(),
896
        }
897
    }
898
899
    fn huff_encode(src: &[u8]) -> BytesMut {
900
        let mut buf = BytesMut::new();
901
        huffman::encode(src, &mut buf);
902
        buf
903
    }
904
905
    #[test]
906
    fn test_decode_continuation_header_with_non_huff_encoded_name() {
907
        let mut de = Decoder::new(0);
908
        let value = huff_encode(b"bar");
909
        let mut buf = BytesMut::new();
910
        // header name is non_huff encoded
911
        buf.extend([0b01000000, 3]);
912
        buf.extend(b"foo");
913
        // header value is partial
914
        buf.extend([0x80 | 3]);
915
        buf.extend(&value[0..1]);
916
917
        let mut res = vec![];
918
        let e = de
919
            .decode(&mut Cursor::new(&mut buf), |h| {
920
                res.push(h);
921
                ControlFlow::Continue(())
922
            })
923
            .unwrap_err();
924
        // decode error because the header value is partial
925
        assert_eq!(e, DecoderError::NeedMore(NeedMore::StringUnderflow));
926
927
        // extend buf with the remaining header value
928
        buf.extend(&value[1..]);
929
        de.decode(&mut Cursor::new(&mut buf), |h| {
930
            res.push(h);
931
            ControlFlow::Continue(())
932
        })
933
        .unwrap();
934
935
        assert_eq!(res.len(), 1);
936
        assert_eq!(de.table.size(), 0);
937
938
        match res[0] {
939
            Header::Field {
940
                ref name,
941
                ref value,
942
            } => {
943
                assert_eq!(name, "foo");
944
                assert_eq!(value, "bar");
945
            }
946
            _ => panic!(),
947
        }
948
    }
949
}