From e61788a57f8442d85aeef8873ff3a965a5d1815c Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Thu, 22 Mar 2018 12:58:23 -0700 Subject: [PATCH] Accept HPACK literals greater than max size (#244) The spec specifically allows accepting HPACK literals with indexing when the HPACK literal is greater than the max table size. In this case, the literal is not inserted in the table. Fixes #243 --- src/hpack/decoder.rs | 103 ++++++++++++++++++++++++++++++------------- 1 file changed, 72 insertions(+), 31 deletions(-) diff --git a/src/hpack/decoder.rs b/src/hpack/decoder.rs index 514c09f..58ec7c7 100644 --- a/src/hpack/decoder.rs +++ b/src/hpack/decoder.rs @@ -482,10 +482,12 @@ impl Table { self.reserve(len); - self.size += len; + if self.size + len <= self.max_size { + self.size += len; - // Track the entry - self.entries.push_front(entry); + // Track the entry + self.entries.push_front(entry); + } } fn set_max_size(&mut self, size: usize) { @@ -495,14 +497,13 @@ impl Table { } fn reserve(&mut self, size: usize) { - debug_assert!(size <= self.max_size); - while self.size + size > self.max_size { - let last = self.entries - .pop_back() - .expect("size of table != 0, but no headers left!"); - - self.size -= last.len(); + match self.entries.pop_back() { + Some(last) => { + self.size -= last.len(); + } + None => return, + } } } @@ -785,27 +786,67 @@ fn from_static(s: &'static str) -> String { unsafe { String::from_utf8_unchecked(Bytes::from_static(s.as_bytes())) } } -#[test] -fn test_peek_u8() { - let b = 0xff; - let mut buf = Cursor::new(vec![b]); - assert_eq!(peek_u8(&mut buf), Some(b)); - assert_eq!(buf.get_u8(), b); - assert_eq!(peek_u8(&mut buf), None); -} +#[cfg(test)] +mod test { + use super::*; + use hpack::Header; -#[test] -fn test_decode_string_empty() { - let mut de = Decoder::new(0); - let mut buf = BytesMut::new(); - let err = de.decode_string(&mut Cursor::new(&mut buf)).unwrap_err(); - assert_eq!(err, DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream)); -} + #[test] + fn test_peek_u8() { + let b = 0xff; + let mut buf = Cursor::new(vec![b]); + assert_eq!(peek_u8(&mut buf), Some(b)); + assert_eq!(buf.get_u8(), b); + assert_eq!(peek_u8(&mut buf), None); + } -#[test] -fn test_decode_empty() { - let mut de = Decoder::new(0); - let mut buf = BytesMut::new(); - let empty = de.decode(&mut Cursor::new(&mut buf), |_| {}).unwrap(); - assert_eq!(empty, ()); + #[test] + fn test_decode_string_empty() { + let mut de = Decoder::new(0); + let mut buf = BytesMut::new(); + let err = de.decode_string(&mut Cursor::new(&mut buf)).unwrap_err(); + assert_eq!(err, DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream)); + } + + #[test] + fn test_decode_empty() { + let mut de = Decoder::new(0); + let mut buf = BytesMut::new(); + let empty = de.decode(&mut Cursor::new(&mut buf), |_| {}).unwrap(); + assert_eq!(empty, ()); + } + + #[test] + fn test_decode_indexed_larger_than_table() { + let mut de = Decoder::new(0); + + let mut buf = vec![0b01000000, 0x80 | 2]; + buf.extend(huff_encode(b"foo")); + buf.extend(&[0x80 | 3]); + buf.extend(huff_encode(b"bar")); + + let mut buf = buf.into(); + + let mut res = vec![]; + let _ = de.decode(&mut Cursor::new(&mut buf), |h| { + res.push(h); + }).unwrap(); + + assert_eq!(res.len(), 1); + assert_eq!(de.table.size(), 0); + + match res[0] { + Header::Field { ref name, ref value } => { + assert_eq!(name, "foo"); + assert_eq!(value, "bar"); + } + _ => panic!(), + } + } + + fn huff_encode(src: &[u8]) -> BytesMut { + let mut buf = BytesMut::new(); + huffman::encode(src, &mut buf).unwrap(); + buf + } }