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 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. | ||||
|  | ||||
| pub(crate) enum Client {} | ||||
| @@ -99,13 +138,8 @@ impl Http1Transaction for Server { | ||||
|         headers.reserve(headers_len); | ||||
|  | ||||
|         for header in &headers_indices[..headers_len] { | ||||
|             let name = HeaderName::from_bytes(&slice[header.name.0..header.name.1]) | ||||
|                 .expect("header name already validated"); | ||||
|             let val = slice.slice(header.value.0, header.value.1); | ||||
|             // Unsafe: httparse already validated header value | ||||
|             let value = unsafe { | ||||
|                 HeaderValue::from_shared_unchecked(val) | ||||
|             }; | ||||
|             let name = header_name!(&slice[header.name.0..header.name.1]); | ||||
|             let value = header_value!(slice.slice(header.value.0, header.value.1)); | ||||
|  | ||||
|             match name { | ||||
|                 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]) { | ||||
|     for header in indices { | ||||
|         let name = HeaderName::from_bytes(&slice[header.name.0..header.name.1]) | ||||
|             .expect("header name already validated"); | ||||
|         let value = unsafe { | ||||
|             HeaderValue::from_shared_unchecked( | ||||
|                 slice.slice(header.value.0, header.value.1) | ||||
|             ) | ||||
|         }; | ||||
|         let name = header_name!(&slice[header.name.0..header.name.1]); | ||||
|         let value = header_value!(slice.slice(header.value.0, header.value.1)); | ||||
|         headers.append(name, value); | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user