refactor(h1): give better panics in debug mode when headers successfully parse illegal values
This commit is contained in:
		| @@ -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); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user