refactor(h1): give better panics in debug mode when headers successfully parse illegal values

This commit is contained in:
Sean McArthur
2018-06-28 12:53:36 -07:00
parent f2d464ac79
commit e7c7f2db05

View File

@@ -14,6 +14,45 @@ use proto::h1::{Encode, Encoder, Http1Transaction, ParseResult, ParseContext, Pa
const MAX_HEADERS: usize = 100; const MAX_HEADERS: usize = 100;
const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific
macro_rules! header_name {
($bytes:expr) => ({
#[cfg(debug_assertions)]
{
match HeaderName::from_bytes($bytes) {
Ok(name) => name,
Err(_) => panic!("illegal header name from httparse: {:?}", Bytes::from($bytes)),
}
}
#[cfg(not(debug_assertions))]
{
HeaderName::from_bytes($bytes)
.expect("header name validated by httparse")
}
});
}
macro_rules! header_value {
($bytes:expr) => ({
#[cfg(debug_assertions)]
{
let __hvb: Bytes = $bytes;
match HeaderValue::from_shared(__hvb.clone()) {
Ok(name) => name,
Err(_) => panic!("illegal header value from httparse: {:?}", __hvb),
}
}
#[cfg(not(debug_assertions))]
{
// Unsafe: httparse already validated header value
unsafe {
HeaderValue::from_shared_unchecked($bytes)
}
}
});
}
// There are 2 main roles, Client and Server. // There are 2 main roles, Client and Server.
pub(crate) enum Client {} pub(crate) enum Client {}
@@ -99,13 +138,8 @@ impl Http1Transaction for Server {
headers.reserve(headers_len); headers.reserve(headers_len);
for header in &headers_indices[..headers_len] { for header in &headers_indices[..headers_len] {
let name = HeaderName::from_bytes(&slice[header.name.0..header.name.1]) let name = header_name!(&slice[header.name.0..header.name.1]);
.expect("header name already validated"); let value = header_value!(slice.slice(header.value.0, header.value.1));
let val = slice.slice(header.value.0, header.value.1);
// Unsafe: httparse already validated header value
let value = unsafe {
HeaderValue::from_shared_unchecked(val)
};
match name { match name {
header::TRANSFER_ENCODING => { header::TRANSFER_ENCODING => {
@@ -875,13 +909,8 @@ fn record_header_indices(bytes: &[u8], headers: &[httparse::Header], indices: &m
fn fill_headers(headers: &mut HeaderMap, slice: Bytes, indices: &[HeaderIndices]) { fn fill_headers(headers: &mut HeaderMap, slice: Bytes, indices: &[HeaderIndices]) {
for header in indices { for header in indices {
let name = HeaderName::from_bytes(&slice[header.name.0..header.name.1]) let name = header_name!(&slice[header.name.0..header.name.1]);
.expect("header name already validated"); let value = header_value!(slice.slice(header.value.0, header.value.1));
let value = unsafe {
HeaderValue::from_shared_unchecked(
slice.slice(header.value.0, header.value.1)
)
};
headers.append(name, value); headers.append(name, value);
} }
} }