Skip to content

Commit 478f7b9

Browse files
f0rkiMichael RodlerDaniele Ahmed
authored
Fix for invalid header panic corrected (#695)
* Revert "fix panic on receiving invalid headers frame by making the `take_request` function return a Result" This reverts commit 66c36c4. * proper fix for the panic in server receiving a request with a :status pseudo-header in the informational range of status codes --------- Signed-off-by: Michael Rodler <[email protected]> Co-authored-by: Michael Rodler <[email protected]> Co-authored-by: Daniele Ahmed <[email protected]>
1 parent 864430c commit 478f7b9

File tree

4 files changed

+36
-33
lines changed

4 files changed

+36
-33
lines changed

src/proto/streams/recv.rs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,11 @@ impl Recv {
229229
return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR).into());
230230
}
231231

232+
if pseudo.status.is_some() && counts.peer().is_server() {
233+
proto_err!(stream: "cannot use :status header for requests; stream={:?}", stream.id);
234+
return Err(Error::library_reset(stream.id, Reason::PROTOCOL_ERROR).into());
235+
}
236+
232237
if !pseudo.is_informational() {
233238
let message = counts
234239
.peer()
@@ -239,27 +244,31 @@ impl Recv {
239244
.pending_recv
240245
.push_back(&mut self.buffer, Event::Headers(message));
241246
stream.notify_recv();
242-
}
243247

244-
// Only servers can receive a headers frame that initiates the stream.
245-
// This is verified in `Streams` before calling this function.
246-
if counts.peer().is_server() {
247-
self.pending_accept.push(stream);
248+
// Only servers can receive a headers frame that initiates the stream.
249+
// This is verified in `Streams` before calling this function.
250+
if counts.peer().is_server() {
251+
// Correctness: never push a stream to `pending_accept` without having the
252+
// corresponding headers frame pushed to `stream.pending_recv`.
253+
self.pending_accept.push(stream);
254+
}
248255
}
249256

250257
Ok(())
251258
}
252259

253260
/// Called by the server to get the request
254-
pub fn take_request(&mut self, stream: &mut store::Ptr) -> Result<Request<()>, proto::Error> {
261+
///
262+
/// # Panics
263+
///
264+
/// Panics if `stream.pending_recv` has no `Event::Headers` queued.
265+
///
266+
pub fn take_request(&mut self, stream: &mut store::Ptr) -> Request<()> {
255267
use super::peer::PollMessage::*;
256268

257269
match stream.pending_recv.pop_front(&mut self.buffer) {
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-
}
270+
Some(Event::Headers(Server(request))) => request,
271+
_ => unreachable!("server stream queue must start with Headers"),
263272
}
264273
}
265274

src/proto/streams/streams.rs

Lines changed: 1 addition & 1 deletion
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) -> Result<Request<()>, proto::Error> {
1181+
pub fn take_request(&self) -> Request<()> {
11821182
let mut me = self.opaque.inner.lock().unwrap();
11831183
let me = &mut *me;
11841184

src/server.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -425,20 +425,13 @@ where
425425

426426
if let Some(inner) = self.connection.next_incoming() {
427427
tracing::trace!("received incoming");
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()));
428+
let (head, _) = inner.take_request().into_parts();
429+
let body = RecvStream::new(FlowControl::new(inner.clone_to_opaque()));
432430

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

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

444437
Poll::Pending

tests/h2-tests/tests/server.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,29 +1380,30 @@ async fn reject_non_authority_target_on_connect_request() {
13801380
}
13811381

13821382
#[tokio::test]
1383-
async fn reject_response_headers_in_request() {
1383+
async fn reject_informational_status_header_in_request() {
13841384
h2_support::trace_init!();
13851385

13861386
let (io, mut client) = mock::new();
13871387

13881388
let client = async move {
13891389
let _ = client.assert_server_handshake().await;
13901390

1391-
client.send_frame(frames::headers(1).response(128)).await;
1391+
let status_code = 128;
1392+
assert!(StatusCode::from_u16(status_code)
1393+
.unwrap()
1394+
.is_informational());
13921395

1393-
// TODO: is CANCEL the right error code to expect here?
1394-
client.recv_frame(frames::reset(1).cancel()).await;
1396+
client
1397+
.send_frame(frames::headers(1).response(status_code))
1398+
.await;
1399+
1400+
client.recv_frame(frames::reset(1).protocol_error()).await;
13951401
};
13961402

13971403
let srv = async move {
13981404
let builder = server::Builder::new();
13991405
let mut srv = builder.handshake::<_, Bytes>(io).await.expect("handshake");
14001406

1401-
let res = srv.next().await;
1402-
tracing::warn!("{:?}", res);
1403-
assert!(res.is_some());
1404-
assert!(res.unwrap().is_err());
1405-
14061407
poll_fn(move |cx| srv.poll_closed(cx))
14071408
.await
14081409
.expect("server");

0 commit comments

Comments
 (0)