Skip to content

Commit e7c7f2d

Browse files
committed
refactor(h1): give better panics in debug mode when headers successfully parse illegal values
1 parent f2d464a commit e7c7f2d

File tree

1 file changed

+43
-14
lines changed

1 file changed

+43
-14
lines changed

src/proto/h1/role.rs

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,45 @@ use proto::h1::{Encode, Encoder, Http1Transaction, ParseResult, ParseContext, Pa
1414
const MAX_HEADERS: usize = 100;
1515
const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific
1616

17+
macro_rules! header_name {
18+
($bytes:expr) => ({
19+
#[cfg(debug_assertions)]
20+
{
21+
match HeaderName::from_bytes($bytes) {
22+
Ok(name) => name,
23+
Err(_) => panic!("illegal header name from httparse: {:?}", Bytes::from($bytes)),
24+
}
25+
}
26+
27+
#[cfg(not(debug_assertions))]
28+
{
29+
HeaderName::from_bytes($bytes)
30+
.expect("header name validated by httparse")
31+
}
32+
});
33+
}
34+
35+
macro_rules! header_value {
36+
($bytes:expr) => ({
37+
#[cfg(debug_assertions)]
38+
{
39+
let __hvb: Bytes = $bytes;
40+
match HeaderValue::from_shared(__hvb.clone()) {
41+
Ok(name) => name,
42+
Err(_) => panic!("illegal header value from httparse: {:?}", __hvb),
43+
}
44+
}
45+
46+
#[cfg(not(debug_assertions))]
47+
{
48+
// Unsafe: httparse already validated header value
49+
unsafe {
50+
HeaderValue::from_shared_unchecked($bytes)
51+
}
52+
}
53+
});
54+
}
55+
1756
// There are 2 main roles, Client and Server.
1857

1958
pub(crate) enum Client {}
@@ -99,13 +138,8 @@ impl Http1Transaction for Server {
99138
headers.reserve(headers_len);
100139

101140
for header in &headers_indices[..headers_len] {
102-
let name = HeaderName::from_bytes(&slice[header.name.0..header.name.1])
103-
.expect("header name already validated");
104-
let val = slice.slice(header.value.0, header.value.1);
105-
// Unsafe: httparse already validated header value
106-
let value = unsafe {
107-
HeaderValue::from_shared_unchecked(val)
108-
};
141+
let name = header_name!(&slice[header.name.0..header.name.1]);
142+
let value = header_value!(slice.slice(header.value.0, header.value.1));
109143

110144
match name {
111145
header::TRANSFER_ENCODING => {
@@ -875,13 +909,8 @@ fn record_header_indices(bytes: &[u8], headers: &[httparse::Header], indices: &m
875909

876910
fn fill_headers(headers: &mut HeaderMap, slice: Bytes, indices: &[HeaderIndices]) {
877911
for header in indices {
878-
let name = HeaderName::from_bytes(&slice[header.name.0..header.name.1])
879-
.expect("header name already validated");
880-
let value = unsafe {
881-
HeaderValue::from_shared_unchecked(
882-
slice.slice(header.value.0, header.value.1)
883-
)
884-
};
912+
let name = header_name!(&slice[header.name.0..header.name.1]);
913+
let value = header_value!(slice.slice(header.value.0, header.value.1));
885914
headers.append(name, value);
886915
}
887916
}

0 commit comments

Comments
 (0)