// Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Fuzzing support for QPACK. #[cfg(feature = "build-fuzzing-corpus")] pub use write_corpus::write_item_to_fuzzing_corpus; #[cfg(feature = "build-fuzzing-corpus")] /// Helpers to write data to the fuzzing corpus. mod write_corpus { use neqo_transport::StreamId; /// Write QPACK data to the fuzzing corpus. pub fn write_item_to_fuzzing_corpus(stream_id: StreamId, buf: &[u8]) { let mut data = Vec::with_capacity(size_of::() + buf.len()); data.extend_from_slice(&stream_id.as_u64().to_le_bytes()); data.extend_from_slice(buf); neqo_common::write_item_to_fuzzing_corpus("qpack", &data); } } #[cfg(fuzzing)] /// Helpers to support fuzzing. mod fuzzing { use crate::{ reader::{ReadByte, Reader}, Decoder, Error, Res, }; /// Buffer wrapper that implements `ReadByte` and `Reader` for a byte slice. /// Returns `NeedMoreData` when the buffer is exhausted. struct BufferReader<'a> { buf: &'a [u8], offset: usize, } impl ReadByte for BufferReader<'_> { fn read_byte(&mut self) -> Res { if self.offset < self.buf.len() { let b = self.buf[self.offset]; self.offset += 1; Ok(b) } else { Err(Error::NeedMoreData) } } } impl Reader for BufferReader<'_> { fn read(&mut self, buf: &mut [u8]) -> Res { let available = self.buf.len() - self.offset; let to_read = buf.len().min(available); buf[..to_read].copy_from_slice(&self.buf[self.offset..self.offset + to_read]); self.offset += to_read; Ok(to_read) } } impl<'a> BufferReader<'a> { const fn new(buf: &'a [u8]) -> Self { Self { buf, offset: 0 } } } fn map_error(err: Error) -> Error { if err == Error::ClosedCriticalStream { Error::ClosedCriticalStream } else { Error::EncoderStream } } impl Decoder { /// Processes encoder stream data from a byte buffer. /// This populates the dynamic table with header entries from encoder instructions. /// /// # Errors /// /// May return `Error::EncoderStream` if the encoder instructions are malformed. pub fn receive_encoder_stream(&mut self, buf: &[u8]) -> Res<()> { let mut recv = BufferReader::new(buf); self.process_instructions(&mut recv).map_err(map_error) } } }