Revision control
Copy as Markdown
Other Tools
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// 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::<u64>() + 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<u8> {
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<usize> {
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)
}
}
}