reset streams when receiving invalid psuedo headers

This commit is contained in:
Sean McArthur
2017-10-06 10:54:49 -07:00
parent 7d1732a70d
commit 431442735d
6 changed files with 55 additions and 6 deletions

View File

@@ -211,6 +211,11 @@ impl Headers {
(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 {
&self.header_block.fields
}

View File

@@ -513,15 +513,15 @@ impl proto::Peer for Peer {
let mut parts = uri::Parts::default();
if let Some(scheme) = pseudo.scheme {
// TODO: Don't unwrap
parts.scheme = Some(uri::Scheme::from_shared(scheme.into_inner()).unwrap());
parts.scheme = Some(uri::Scheme::from_shared(scheme.into_inner())
.or_else(|_| malformed!())?);
} else {
malformed!();
}
if let Some(authority) = pseudo.authority {
// TODO: Don't unwrap
parts.authority = Some(uri::Authority::from_shared(authority.into_inner()).unwrap());
parts.authority = Some(uri::Authority::from_shared(authority.into_inner())
.or_else(|_| malformed!())?);
}
if let Some(path) = pseudo.path {
@@ -530,8 +530,8 @@ impl proto::Peer for Peer {
malformed!();
}
// TODO: Don't unwrap
parts.path_and_query = Some(uri::PathAndQuery::from_shared(path.into_inner()).unwrap());
parts.path_and_query = Some(uri::PathAndQuery::from_shared(path.into_inner())
.or_else(|_| malformed!())?);
}
b.uri(parts);

View File

@@ -58,3 +58,30 @@ fn serve_request() {
#[test]
#[ignore]
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");
}

View File

@@ -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 {
fn from(src: Mock<frame::Headers>) -> Self {
Frame::Headers(src.0)
@@ -234,6 +240,11 @@ impl From<Mock<frame::GoAway>> for SendFrame {
// ==== Reset helpers
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 {
let id = self.0.stream_id();
Mock(frame::Reset::new(id, frame::Reason::FlowControlError))

View File

@@ -12,6 +12,7 @@ pub extern crate futures;
pub extern crate h2;
pub extern crate http;
pub extern crate mock_io;
pub extern crate string;
pub extern crate tokio_io;
// Kind of annoying, but we can't use macros from crates that aren't specified

View File

@@ -1,8 +1,13 @@
use h2::client;
use super::string::{String, TryFrom};
use bytes::Bytes;
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 {
WaitForCapacity {
stream: Some(stream),