Skip to content

Commit 55d9a58

Browse files
authored
refactor(http1): return Parse::Internal error if there's an illegal header name or value (#2544)
1 parent 6a6a240 commit 55d9a58

File tree

2 files changed

+20
-27
lines changed

2 files changed

+20
-27
lines changed

src/error.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ pub(super) enum Parse {
7373
Header,
7474
TooLarge,
7575
Status,
76+
#[cfg_attr(debug_assertions, allow(unused))]
77+
Internal,
7678
}
7779

7880
#[derive(Debug, PartialEq)]
@@ -374,6 +376,9 @@ impl Error {
374376
Kind::Parse(Parse::Header) => "invalid HTTP header parsed",
375377
Kind::Parse(Parse::TooLarge) => "message head is too large",
376378
Kind::Parse(Parse::Status) => "invalid HTTP status-code parsed",
379+
Kind::Parse(Parse::Internal) => {
380+
"internal error inside Hyper and/or its dependencies, please report"
381+
}
377382
Kind::IncompleteMessage => "connection closed before message completed",
378383
#[cfg(feature = "http1")]
379384
Kind::UnexpectedMessage => "received unexpected message from connection",

src/proto/h1/role.rs

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ use std::mem;
88
#[cfg(any(test, feature = "server", feature = "ffi"))]
99
use bytes::Bytes;
1010
use bytes::BytesMut;
11-
use http::header::{self, Entry, HeaderName, HeaderValue};
1211
#[cfg(feature = "server")]
1312
use http::header::ValueIter;
13+
use http::header::{self, Entry, HeaderName, HeaderValue};
1414
use http::{HeaderMap, Method, StatusCode, Version};
1515

1616
use crate::body::DecodedLength;
@@ -29,46 +29,35 @@ const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific
2929

3030
macro_rules! header_name {
3131
($bytes:expr) => {{
32-
#[cfg(debug_assertions)]
3332
{
3433
match HeaderName::from_bytes($bytes) {
3534
Ok(name) => name,
36-
Err(_) => panic!(
37-
"illegal header name from httparse: {:?}",
38-
::bytes::Bytes::copy_from_slice($bytes)
39-
),
40-
}
41-
}
42-
43-
#[cfg(not(debug_assertions))]
44-
{
45-
match HeaderName::from_bytes($bytes) {
46-
Ok(name) => name,
47-
Err(_) => panic!("illegal header name from httparse: {:?}", $bytes),
35+
Err(e) => maybe_panic!(e),
4836
}
4937
}
5038
}};
5139
}
5240

5341
macro_rules! header_value {
5442
($bytes:expr) => {{
55-
#[cfg(debug_assertions)]
5643
{
57-
let __hvb: ::bytes::Bytes = $bytes;
58-
match HeaderValue::from_maybe_shared(__hvb.clone()) {
59-
Ok(name) => name,
60-
Err(_) => panic!("illegal header value from httparse: {:?}", __hvb),
61-
}
62-
}
63-
64-
#[cfg(not(debug_assertions))]
65-
{
66-
// Unsafe: httparse already validated header value
6744
unsafe { HeaderValue::from_maybe_shared_unchecked($bytes) }
6845
}
6946
}};
7047
}
7148

49+
macro_rules! maybe_panic {
50+
($($arg:tt)*) => ({
51+
let _err = ($($arg)*);
52+
if cfg!(debug_assertions) {
53+
panic!("{:?}", _err);
54+
} else {
55+
error!("Internal Hyper error, please report {:?}", _err);
56+
return Err(Parse::Internal)
57+
}
58+
})
59+
}
60+
7261
pub(super) fn parse_headers<T>(
7362
bytes: &mut BytesMut,
7463
ctx: ParseContext<'_>,
@@ -891,8 +880,7 @@ impl Http1Transaction for Client {
891880
);
892881
let mut res = httparse::Response::new(&mut headers);
893882
let bytes = buf.as_ref();
894-
match ctx.h1_parser_config.parse_response(&mut res, bytes)
895-
{
883+
match ctx.h1_parser_config.parse_response(&mut res, bytes) {
896884
Ok(httparse::Status::Complete(len)) => {
897885
trace!("Response.parse Complete({})", len);
898886
let status = StatusCode::from_u16(res.code.unwrap())?;

0 commit comments

Comments
 (0)