reset streams when receiving invalid psuedo headers
This commit is contained in:
		| @@ -211,6 +211,11 @@ impl Headers { | |||||||
|         (self.header_block.pseudo, self.header_block.fields) |         (self.header_block.pseudo, self.header_block.fields) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #[cfg(feature = "unstable")] | ||||||
|  |     pub fn pseudo_mut(&mut self) -> &mut Pseudo { | ||||||
|  |         &mut self.header_block.pseudo | ||||||
|  |     } | ||||||
|  |  | ||||||
|     pub fn fields(&self) -> &HeaderMap { |     pub fn fields(&self) -> &HeaderMap { | ||||||
|         &self.header_block.fields |         &self.header_block.fields | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -513,15 +513,15 @@ impl proto::Peer for Peer { | |||||||
|         let mut parts = uri::Parts::default(); |         let mut parts = uri::Parts::default(); | ||||||
|  |  | ||||||
|         if let Some(scheme) = pseudo.scheme { |         if let Some(scheme) = pseudo.scheme { | ||||||
|             // TODO: Don't unwrap |             parts.scheme = Some(uri::Scheme::from_shared(scheme.into_inner()) | ||||||
|             parts.scheme = Some(uri::Scheme::from_shared(scheme.into_inner()).unwrap()); |                 .or_else(|_| malformed!())?); | ||||||
|         } else { |         } else { | ||||||
|             malformed!(); |             malformed!(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if let Some(authority) = pseudo.authority { |         if let Some(authority) = pseudo.authority { | ||||||
|             // TODO: Don't unwrap |             parts.authority = Some(uri::Authority::from_shared(authority.into_inner()) | ||||||
|             parts.authority = Some(uri::Authority::from_shared(authority.into_inner()).unwrap()); |                 .or_else(|_| malformed!())?); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if let Some(path) = pseudo.path { |         if let Some(path) = pseudo.path { | ||||||
| @@ -530,8 +530,8 @@ impl proto::Peer for Peer { | |||||||
|                 malformed!(); |                 malformed!(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // TODO: Don't unwrap |             parts.path_and_query = Some(uri::PathAndQuery::from_shared(path.into_inner()) | ||||||
|             parts.path_and_query = Some(uri::PathAndQuery::from_shared(path.into_inner()).unwrap()); |                 .or_else(|_| malformed!())?); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         b.uri(parts); |         b.uri(parts); | ||||||
|   | |||||||
| @@ -58,3 +58,30 @@ fn serve_request() { | |||||||
| #[test] | #[test] | ||||||
| #[ignore] | #[ignore] | ||||||
| fn accept_with_pending_connections_after_socket_close() {} | fn accept_with_pending_connections_after_socket_close() {} | ||||||
|  |  | ||||||
|  | #[test] | ||||||
|  | fn sent_invalid_authority() { | ||||||
|  |     let _ = ::env_logger::init(); | ||||||
|  |     let (io, client) = mock::new(); | ||||||
|  |  | ||||||
|  |     let bad_auth = util::byte_str("not:a/good authority"); | ||||||
|  |     let mut bad_headers: frame::Headers = frames::headers(1) | ||||||
|  |         .request("GET", "https://example.com/") | ||||||
|  |         .eos() | ||||||
|  |         .into(); | ||||||
|  |     bad_headers.pseudo_mut().authority = Some(bad_auth); | ||||||
|  |  | ||||||
|  |     let client = client | ||||||
|  |         .assert_server_handshake() | ||||||
|  |         .unwrap() | ||||||
|  |         .recv_settings() | ||||||
|  |         .send_frame(bad_headers) | ||||||
|  |         .recv_frame(frames::reset(1).protocol_error()) | ||||||
|  |         .close(); | ||||||
|  |  | ||||||
|  |     let srv = Server::handshake(io) | ||||||
|  |         .expect("handshake") | ||||||
|  |         .and_then(|srv| srv.into_future().unwrap()); | ||||||
|  |  | ||||||
|  |     srv.join(client).wait().expect("wait"); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -136,6 +136,12 @@ impl Mock<frame::Headers> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | impl From<Mock<frame::Headers>> for frame::Headers { | ||||||
|  |     fn from(src: Mock<frame::Headers>) -> Self { | ||||||
|  |         src.0 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| impl From<Mock<frame::Headers>> for SendFrame { | impl From<Mock<frame::Headers>> for SendFrame { | ||||||
|     fn from(src: Mock<frame::Headers>) -> Self { |     fn from(src: Mock<frame::Headers>) -> Self { | ||||||
|         Frame::Headers(src.0) |         Frame::Headers(src.0) | ||||||
| @@ -234,6 +240,11 @@ impl From<Mock<frame::GoAway>> for SendFrame { | |||||||
| // ==== Reset helpers | // ==== Reset helpers | ||||||
|  |  | ||||||
| impl Mock<frame::Reset> { | impl Mock<frame::Reset> { | ||||||
|  |     pub fn protocol_error(self) -> Self { | ||||||
|  |         let id = self.0.stream_id(); | ||||||
|  |         Mock(frame::Reset::new(id, frame::Reason::ProtocolError)) | ||||||
|  |     } | ||||||
|  |  | ||||||
|     pub fn flow_control(self) -> Self { |     pub fn flow_control(self) -> Self { | ||||||
|         let id = self.0.stream_id(); |         let id = self.0.stream_id(); | ||||||
|         Mock(frame::Reset::new(id, frame::Reason::FlowControlError)) |         Mock(frame::Reset::new(id, frame::Reason::FlowControlError)) | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ pub extern crate futures; | |||||||
| pub extern crate h2; | pub extern crate h2; | ||||||
| pub extern crate http; | pub extern crate http; | ||||||
| pub extern crate mock_io; | pub extern crate mock_io; | ||||||
|  | pub extern crate string; | ||||||
| pub extern crate tokio_io; | pub extern crate tokio_io; | ||||||
|  |  | ||||||
| // Kind of annoying, but we can't use macros from crates that aren't specified | // Kind of annoying, but we can't use macros from crates that aren't specified | ||||||
|   | |||||||
| @@ -1,8 +1,13 @@ | |||||||
| use h2::client; | use h2::client; | ||||||
|  |  | ||||||
|  | use super::string::{String, TryFrom}; | ||||||
| use bytes::Bytes; | use bytes::Bytes; | ||||||
| use futures::{Async, Future, Poll}; | use futures::{Async, Future, Poll}; | ||||||
|  |  | ||||||
|  | pub fn byte_str(s: &str) -> String<Bytes> { | ||||||
|  |     String::try_from(Bytes::from(s)).unwrap() | ||||||
|  | } | ||||||
|  |  | ||||||
| pub fn wait_for_capacity(stream: client::Stream<Bytes>, target: usize) -> WaitForCapacity { | pub fn wait_for_capacity(stream: client::Stream<Bytes>, target: usize) -> WaitForCapacity { | ||||||
|     WaitForCapacity { |     WaitForCapacity { | ||||||
|         stream: Some(stream), |         stream: Some(stream), | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user