diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/neqo-qpack/src/reader.rs | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/neqo-qpack/src/reader.rs')
-rw-r--r-- | third_party/rust/neqo-qpack/src/reader.rs | 586 |
1 files changed, 586 insertions, 0 deletions
diff --git a/third_party/rust/neqo-qpack/src/reader.rs b/third_party/rust/neqo-qpack/src/reader.rs new file mode 100644 index 0000000000..386a25ffc1 --- /dev/null +++ b/third_party/rust/neqo-qpack/src/reader.rs @@ -0,0 +1,586 @@ +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::huffman::decode_huffman; +use crate::prefix::Prefix; +use crate::{Error, Res}; +use neqo_common::{qdebug, qerror}; +use neqo_transport::{Connection, StreamId}; +use std::convert::TryInto; +use std::mem; +use std::str; + +pub trait ReadByte { + /// # Errors + /// Return error occurred while reading a byte. + /// The exact error depends on trait implementation. + fn read_byte(&mut self) -> Res<u8>; +} + +pub trait Reader { + /// # Errors + /// Return error occurred while reading date into a buffer. + /// The exact error depends on trait implementation. + fn read(&mut self, buf: &mut [u8]) -> Res<usize>; +} + +pub(crate) struct ReceiverConnWrapper<'a> { + conn: &'a mut Connection, + stream_id: StreamId, +} + +impl<'a> ReadByte for ReceiverConnWrapper<'a> { + fn read_byte(&mut self) -> Res<u8> { + let mut b = [0]; + match self.conn.stream_recv(self.stream_id, &mut b)? { + (_, true) => Err(Error::ClosedCriticalStream), + (0, false) => Err(Error::NeedMoreData), + _ => Ok(b[0]), + } + } +} + +impl<'a> Reader for ReceiverConnWrapper<'a> { + fn read(&mut self, buf: &mut [u8]) -> Res<usize> { + match self.conn.stream_recv(self.stream_id, buf)? { + (_, true) => Err(Error::ClosedCriticalStream), + (amount, false) => Ok(amount), + } + } +} + +impl<'a> ReceiverConnWrapper<'a> { + pub fn new(conn: &'a mut Connection, stream_id: StreamId) -> Self { + Self { conn, stream_id } + } +} + +/// This is only used by header decoder therefore all errors are `DecompressionFailed`. +/// A header block is read entirely before decoding it, therefore if there is not enough +/// data in the buffer an error `DecompressionFailed` will be return. +pub(crate) struct ReceiverBufferWrapper<'a> { + buf: &'a [u8], + offset: usize, +} + +impl<'a> ReadByte for ReceiverBufferWrapper<'a> { + fn read_byte(&mut self) -> Res<u8> { + if self.offset == self.buf.len() { + Err(Error::DecompressionFailed) + } else { + let b = self.buf[self.offset]; + self.offset += 1; + Ok(b) + } + } +} + +impl<'a> ReceiverBufferWrapper<'a> { + pub fn new(buf: &'a [u8]) -> Self { + Self { buf, offset: 0 } + } + + pub fn peek(&self) -> Res<u8> { + if self.offset == self.buf.len() { + Err(Error::DecompressionFailed) + } else { + Ok(self.buf[self.offset]) + } + } + + pub fn done(&self) -> bool { + self.offset == self.buf.len() + } + + /// The function decodes varint with a prefixed, i.e. ignores `prefix_len` bits of the first + /// byte. + /// `ReceiverBufferWrapper` is only used for decoding header blocks. The header blocks are read + /// entirely before a decoding starts, therefore any incomplete varint because of reaching the + /// end of a buffer will be treated as the `DecompressionFailed` error. + pub fn read_prefixed_int(&mut self, prefix_len: u8) -> Res<u64> { + debug_assert!(prefix_len < 8); + + let first_byte = self.read_byte()?; + let mut reader = IntReader::new(first_byte, prefix_len); + reader.read(self) + } + + /// Do not use `LiteralReader` here to avoid copying data. + /// The function decoded a literal with a prefix: + /// 1) ignores `prefix_len` bits of the first byte, + /// 2) reads "huffman bit" + /// 3) decode varint that is the length of a literal + /// 4) reads the literal + /// 5) performs huffman decoding if needed. + /// + /// `ReceiverBufferWrapper` is only used for decoding header blocks. The header blocks are read + /// entirely before a decoding starts, therefore any incomplete varint or literal because of + /// reaching the end of a buffer will be treated as the `DecompressionFailed` error. + pub fn read_literal_from_buffer(&mut self, prefix_len: u8) -> Res<String> { + debug_assert!(prefix_len < 7); + + let first_byte = self.read_byte()?; + let use_huffman = (first_byte & (0x80 >> prefix_len)) != 0; + let mut int_reader = IntReader::new(first_byte, prefix_len + 1); + let length: usize = int_reader + .read(self)? + .try_into() + .or(Err(Error::DecompressionFailed))?; + if use_huffman { + Ok(to_string(&decode_huffman(self.slice(length)?)?)?) + } else { + Ok(to_string(self.slice(length)?)?) + } + } + + fn slice(&mut self, len: usize) -> Res<&[u8]> { + if self.offset + len > self.buf.len() { + Err(Error::DecompressionFailed) + } else { + let start = self.offset; + self.offset += len; + Ok(&self.buf[start..self.offset]) + } + } +} + +/// This is varint reader that can take into account a prefix. +#[derive(Debug)] +pub struct IntReader { + value: u64, + cnt: u8, + done: bool, +} + +impl IntReader { + /// `IntReader` is created by suppling the first byte anf prefix length. + /// A varint may take only one byte, In that case already the first by has set state to done. + /// # Panics + /// When `prefix_len` is 8 or larger. + #[must_use] + pub fn new(first_byte: u8, prefix_len: u8) -> Self { + debug_assert!(prefix_len < 8, "prefix cannot larger than 7."); + let mask = if prefix_len == 0 { + 0xff + } else { + (1 << (8 - prefix_len)) - 1 + }; + let value = u64::from(first_byte & mask); + + Self { + value, + cnt: 0, + done: value < u64::from(mask), + } + } + + /// # Panics + /// Never, but rust doesn't know that. + #[must_use] + pub fn make(first_byte: u8, prefixes: &[Prefix]) -> Self { + for prefix in prefixes { + if prefix.cmp_prefix(first_byte) { + return Self::new(first_byte, prefix.len()); + } + } + unreachable!(); + } + + /// This function reads bytes until the varint is decoded or until stream/buffer does not + /// have any more date. + /// # Errors + /// Possible errors are: + /// 1) `NeedMoreData` if the reader needs more data, + /// 2) `IntegerOverflow`, + /// 3) Any `ReadByte`'s error + pub fn read<R: ReadByte>(&mut self, s: &mut R) -> Res<u64> { + let mut b: u8; + while !self.done { + b = s.read_byte()?; + + if (self.cnt == 63) && (b > 1 || (b == 1 && ((self.value >> 63) == 1))) { + qerror!("Error decoding prefixed encoded int - IntegerOverflow"); + return Err(Error::IntegerOverflow); + } + self.value += u64::from(b & 0x7f) << self.cnt; + if (b & 0x80) == 0 { + self.done = true; + } + self.cnt += 7; + if self.cnt >= 64 { + self.done = true; + } + } + Ok(self.value) + } +} + +#[derive(Debug)] +enum LiteralReaderState { + ReadHuffman, + ReadLength { reader: IntReader }, + ReadLiteral { offset: usize }, + Done, +} + +impl Default for LiteralReaderState { + fn default() -> Self { + Self::ReadHuffman + } +} + +/// This is decoder of a literal with a prefix: +/// 1) ignores `prefix_len` bits of the first byte, +/// 2) reads "huffman bit" +/// 3) decode varint that is the length of a literal +/// 4) reads the literal +/// 5) performs huffman decoding if needed. +#[derive(Debug, Default)] +pub struct LiteralReader { + state: LiteralReaderState, + literal: Vec<u8>, + use_huffman: bool, +} + +impl LiteralReader { + /// Creates `LiteralReader` with the first byte. This constructor is always used + /// when a litreral has a prefix. + /// For literals without a prefix please use the default constructor. + /// # Panics + /// If `prefix_len` is 8 or more. + #[must_use] + pub fn new_with_first_byte(first_byte: u8, prefix_len: u8) -> Self { + assert!(prefix_len < 8); + Self { + state: LiteralReaderState::ReadLength { + reader: IntReader::new(first_byte, prefix_len + 1), + }, + literal: Vec::new(), + use_huffman: (first_byte & (0x80 >> prefix_len)) != 0, + } + } + + /// This function reads bytes until the literal is decoded or until stream/buffer does not + /// have any more date ready. + /// # Errors + /// Possible errors are: + /// 1) `NeedMoreData` if the reader needs more data, + /// 2) `IntegerOverflow` + /// 3) Any `ReadByte`'s error + /// It returns value if reading the literal is done or None if it needs more data. + /// # Panics + /// When this object is complete. + pub fn read<T: ReadByte + Reader>(&mut self, s: &mut T) -> Res<Vec<u8>> { + loop { + qdebug!("state = {:?}", self.state); + match &mut self.state { + LiteralReaderState::ReadHuffman => { + let b = s.read_byte()?; + + self.use_huffman = (b & 0x80) != 0; + self.state = LiteralReaderState::ReadLength { + reader: IntReader::new(b, 1), + }; + } + LiteralReaderState::ReadLength { reader } => { + let v = reader.read(s)?; + self.literal + .resize(v.try_into().or(Err(Error::Decoding))?, 0x0); + self.state = LiteralReaderState::ReadLiteral { offset: 0 }; + } + LiteralReaderState::ReadLiteral { offset } => { + let amount = s.read(&mut self.literal[*offset..])?; + *offset += amount; + if *offset == self.literal.len() { + self.state = LiteralReaderState::Done; + if self.use_huffman { + break Ok(decode_huffman(&self.literal)?); + } + break Ok(mem::take(&mut self.literal)); + } + break Err(Error::NeedMoreData); + } + LiteralReaderState::Done => { + panic!("Should not call read() in this state."); + } + } + } + } +} + +/// This is a helper function used only by `ReceiverBufferWrapper`, therefore it returns +/// `DecompressionFailed` if any error happens. +/// # Errors +/// If an parsing error occurred, the function returns `ToStringFailed`. +pub fn to_string(v: &[u8]) -> Res<String> { + match str::from_utf8(v) { + Ok(s) => Ok(s.to_string()), + Err(_) => Err(Error::ToStringFailed), + } +} + +#[cfg(test)] +pub(crate) mod test_receiver { + + use super::{Error, ReadByte, Reader, Res}; + use std::collections::VecDeque; + + #[derive(Default)] + pub struct TestReceiver { + buf: VecDeque<u8>, + } + + impl ReadByte for TestReceiver { + fn read_byte(&mut self) -> Res<u8> { + self.buf.pop_back().ok_or(Error::NeedMoreData) + } + } + + impl Reader for TestReceiver { + fn read(&mut self, buf: &mut [u8]) -> Res<usize> { + let len = if buf.len() > self.buf.len() { + self.buf.len() + } else { + buf.len() + }; + for item in buf.iter_mut().take(len) { + *item = self.buf.pop_back().ok_or(Error::NeedMoreData)?; + } + Ok(len) + } + } + + impl TestReceiver { + pub fn write(&mut self, buf: &[u8]) { + for b in buf { + self.buf.push_front(*b); + } + } + } +} + +#[cfg(test)] +mod tests { + + use super::{ + str, test_receiver, to_string, Error, IntReader, LiteralReader, ReadByte, + ReceiverBufferWrapper, Res, + }; + use test_receiver::TestReceiver; + + const TEST_CASES_NUMBERS: [(&[u8], u8, u64); 7] = [ + (&[0xEA], 3, 10), + (&[0x0A], 3, 10), + (&[0x8A], 3, 10), + (&[0xFF, 0x9A, 0x0A], 3, 1337), + (&[0x1F, 0x9A, 0x0A], 3, 1337), + (&[0x9F, 0x9A, 0x0A], 3, 1337), + (&[0x2A], 0, 42), + ]; + + #[test] + fn read_prefixed_int() { + for (buf, prefix_len, value) in &TEST_CASES_NUMBERS { + let mut reader = IntReader::new(buf[0], *prefix_len); + let mut test_receiver: TestReceiver = TestReceiver::default(); + test_receiver.write(&buf[1..]); + assert_eq!(reader.read(&mut test_receiver), Ok(*value)); + } + } + + #[test] + fn read_prefixed_int_with_more_data_in_buffer() { + for (buf, prefix_len, value) in &TEST_CASES_NUMBERS { + let mut reader = IntReader::new(buf[0], *prefix_len); + let mut test_receiver: TestReceiver = TestReceiver::default(); + test_receiver.write(&buf[1..]); + // add some more data + test_receiver.write(&[0x0, 0x0, 0x0]); + assert_eq!(reader.read(&mut test_receiver), Ok(*value)); + } + } + + #[test] + fn read_prefixed_int_slow_writer() { + let (buf, prefix_len, value) = &TEST_CASES_NUMBERS[4]; + let mut reader = IntReader::new(buf[0], *prefix_len); + let mut test_receiver: TestReceiver = TestReceiver::default(); + + // data has not been received yet, reading IntReader will return Err(Error::NeedMoreData). + assert_eq!(reader.read(&mut test_receiver), Err(Error::NeedMoreData)); + + // Write one byte. + test_receiver.write(&buf[1..2]); + // data has not been received yet, reading IntReader will return Err(Error::NeedMoreData). + assert_eq!(reader.read(&mut test_receiver), Err(Error::NeedMoreData)); + + // Write one byte. + test_receiver.write(&buf[2..]); + // Now prefixed int is complete. + assert_eq!(reader.read(&mut test_receiver), Ok(*value)); + } + + type TestSetup = (&'static [u8], u8, Res<u64>); + const TEST_CASES_BIG_NUMBERS: [TestSetup; 3] = [ + ( + &[ + 0xFF, 0x80, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + ], + 0, + Ok(0xFFFF_FFFF_FFFF_FFFF), + ), + ( + &[ + 0xFF, 0x81, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + ], + 0, + Err(Error::IntegerOverflow), + ), + ( + &[ + 0xFF, 0x80, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, + ], + 0, + Err(Error::IntegerOverflow), + ), + ]; + + #[test] + fn read_prefixed_int_big_number() { + for (buf, prefix_len, value) in &TEST_CASES_BIG_NUMBERS { + let mut reader = IntReader::new(buf[0], *prefix_len); + let mut test_receiver: TestReceiver = TestReceiver::default(); + test_receiver.write(&buf[1..]); + assert_eq!(reader.read(&mut test_receiver), *value); + } + } + + const TEST_CASES_LITERAL: [(&[u8], u8, &str); 9] = [ + // No Huffman + ( + &[ + 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79, + ], + 1, + "custom-key", + ), + ( + &[ + 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79, + ], + 3, + "custom-key", + ), + ( + &[ + 0xea, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79, + ], + 3, + "custom-key", + ), + ( + &[ + 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + ], + 1, + "custom-header", + ), + // With Huffman + (&[0x15, 0xae, 0xc3, 0x77, 0x1a, 0x4b], 3, "private"), + ( + &[ + 0x56, 0xd0, 0x7a, 0xbe, 0x94, 0x10, 0x54, 0xd4, 0x44, 0xa8, 0x20, 0x05, 0x95, 0x04, + 0x0b, 0x81, 0x66, 0xe0, 0x82, 0xa6, 0x2d, 0x1b, 0xff, + ], + 1, + "Mon, 21 Oct 2013 20:13:21 GMT", + ), + ( + &[ + 0xff, 0x0f, 0xd0, 0x7a, 0xbe, 0x94, 0x10, 0x54, 0xd4, 0x44, 0xa8, 0x20, 0x05, 0x95, + 0x04, 0x0b, 0x81, 0x66, 0xe0, 0x82, 0xa6, 0x2d, 0x1b, 0xff, + ], + 4, + "Mon, 21 Oct 2013 20:13:21 GMT", + ), + ( + &[ + 0x51, 0x9d, 0x29, 0xad, 0x17, 0x18, 0x63, 0xc7, 0x8f, 0x0b, 0x97, 0xc8, 0xe9, 0xae, + 0x82, 0xae, 0x43, 0xd3, + ], + 1, + "https://www.example.com", + ), + ( + &[ + 0x91, 0x9d, 0x29, 0xad, 0x17, 0x18, 0x63, 0xc7, 0x8f, 0x0b, 0x97, 0xc8, 0xe9, 0xae, + 0x82, 0xae, 0x43, 0xd3, + ], + 0, + "https://www.example.com", + ), + ]; + + #[test] + fn read_literal() { + for (buf, prefix_len, value) in &TEST_CASES_LITERAL { + let mut reader = LiteralReader::new_with_first_byte(buf[0], *prefix_len); + let mut test_receiver: TestReceiver = TestReceiver::default(); + test_receiver.write(&buf[1..]); + assert_eq!( + to_string(&reader.read(&mut test_receiver).unwrap()).unwrap(), + *value + ); + } + } + + #[test] + fn read_prefixed_int_receiver_buffer_wrapper() { + for (buf, prefix_len, value) in &TEST_CASES_NUMBERS { + let mut buffer = ReceiverBufferWrapper::new(buf); + let mut reader = IntReader::new(buffer.read_byte().unwrap(), *prefix_len); + assert_eq!(reader.read(&mut buffer), Ok(*value)); + } + } + + #[test] + fn read_prefixed_int_big_receiver_buffer_wrapper() { + for (buf, prefix_len, value) in &TEST_CASES_BIG_NUMBERS { + let mut buffer = ReceiverBufferWrapper::new(buf); + let mut reader = IntReader::new(buffer.read_byte().unwrap(), *prefix_len); + assert_eq!(reader.read(&mut buffer), *value); + } + } + + #[test] + fn read_literal_receiver_buffer_wrapper() { + for (buf, prefix_len, value) in &TEST_CASES_LITERAL { + let mut buffer = ReceiverBufferWrapper::new(buf); + assert_eq!( + buffer.read_literal_from_buffer(*prefix_len).unwrap(), + *value + ); + } + } + + #[test] + fn read_failure_receiver_buffer_wrapper_number() { + let (buf, prefix_len, _) = &TEST_CASES_NUMBERS[4]; + let mut buffer = ReceiverBufferWrapper::new(&buf[..1]); + let mut reader = IntReader::new(buffer.read_byte().unwrap(), *prefix_len); + assert_eq!(reader.read(&mut buffer), Err(Error::DecompressionFailed)); + } + + #[test] + fn read_failure_receiver_buffer_wrapper_literal() { + let (buf, prefix_len, _) = &TEST_CASES_LITERAL[0]; + let mut buffer = ReceiverBufferWrapper::new(&buf[..6]); + assert_eq!( + buffer.read_literal_from_buffer(*prefix_len), + Err(Error::DecompressionFailed) + ); + } +} |