Skip to content

Commit 66c36c4

Browse files
Michael Rodlerseanmonstar
Michael Rodler
authored andcommitted
fix panic on receiving invalid headers frame by making the take_request function return a Result
Signed-off-by: Michael Rodler <[email protected]> Reviewed-by: Daniele Ahmed <[email protected]>
1 parent 04e6398 commit 66c36c4

File tree

4 files changed

+51
-11
lines changed

4 files changed

+51
-11
lines changed

src/proto/streams/recv.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -251,14 +251,15 @@ impl Recv {
251251
}
252252

253253
/// Called by the server to get the request
254-
///
255-
/// TODO: Should this fn return `Result`?
256-
pub fn take_request(&mut self, stream: &mut store::Ptr) -> Request<()> {
254+
pub fn take_request(&mut self, stream: &mut store::Ptr) -> Result<Request<()>, proto::Error> {
257255
use super::peer::PollMessage::*;
258256

259257
match stream.pending_recv.pop_front(&mut self.buffer) {
260-
Some(Event::Headers(Server(request))) => request,
261-
_ => panic!(),
258+
Some(Event::Headers(Server(request))) => Ok(request),
259+
_ => {
260+
proto_err!(stream: "received invalid request; stream={:?}", stream.id);
261+
Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR))
262+
}
262263
}
263264
}
264265

src/proto/streams/streams.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1178,7 +1178,7 @@ impl<B> StreamRef<B> {
11781178
/// # Panics
11791179
///
11801180
/// This function panics if the request isn't present.
1181-
pub fn take_request(&self) -> Request<()> {
1181+
pub fn take_request(&self) -> Result<Request<()>, proto::Error> {
11821182
let mut me = self.opaque.inner.lock().unwrap();
11831183
let me = &mut *me;
11841184

src/server.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -425,13 +425,20 @@ where
425425

426426
if let Some(inner) = self.connection.next_incoming() {
427427
tracing::trace!("received incoming");
428-
let (head, _) = inner.take_request().into_parts();
429-
let body = RecvStream::new(FlowControl::new(inner.clone_to_opaque()));
428+
match inner.take_request() {
429+
Ok(req) => {
430+
let (head, _) = req.into_parts();
431+
let body = RecvStream::new(FlowControl::new(inner.clone_to_opaque()));
430432

431-
let request = Request::from_parts(head, body);
432-
let respond = SendResponse { inner };
433+
let request = Request::from_parts(head, body);
434+
let respond = SendResponse { inner };
433435

434-
return Poll::Ready(Some(Ok((request, respond))));
436+
return Poll::Ready(Some(Ok((request, respond))));
437+
}
438+
Err(e) => {
439+
return Poll::Ready(Some(Err(e.into())));
440+
}
441+
}
435442
}
436443

437444
Poll::Pending

tests/h2-tests/tests/server.rs

+32
Original file line numberDiff line numberDiff line change
@@ -1378,3 +1378,35 @@ async fn reject_non_authority_target_on_connect_request() {
13781378

13791379
join(client, srv).await;
13801380
}
1381+
1382+
#[tokio::test]
1383+
async fn reject_response_headers_in_request() {
1384+
h2_support::trace_init!();
1385+
1386+
let (io, mut client) = mock::new();
1387+
1388+
let client = async move {
1389+
let _ = client.assert_server_handshake().await;
1390+
1391+
client.send_frame(frames::headers(1).response(128)).await;
1392+
1393+
// TODO: is CANCEL the right error code to expect here?
1394+
client.recv_frame(frames::reset(1).cancel()).await;
1395+
};
1396+
1397+
let srv = async move {
1398+
let builder = server::Builder::new();
1399+
let mut srv = builder.handshake::<_, Bytes>(io).await.expect("handshake");
1400+
1401+
let res = srv.next().await;
1402+
tracing::warn!("{:?}", res);
1403+
assert!(res.is_some());
1404+
assert!(res.unwrap().is_err());
1405+
1406+
poll_fn(move |cx| srv.poll_closed(cx))
1407+
.await
1408+
.expect("server");
1409+
};
1410+
1411+
join(client, srv).await;
1412+
}

0 commit comments

Comments
 (0)