Commit 382a328e authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

Issue connection error if client receives HEADERS with idle stream ID

If stream ID is not idle, it might be valid HEADERS.  If stream ID is
idle, it is invalid regardless stream ID is even or odd, since client
is not expected to recieve request from server.  nghttp2 library
historically allows this, but now we forbids this.
parent babfa414
......@@ -2993,6 +2993,17 @@ int nghttp2_session_on_request_headers_received(nghttp2_session *session,
/* We don't accept new stream after GOAWAY is sent or received. */
return NGHTTP2_ERR_IGN_HEADER_BLOCK;
}
/* If client recieves idle stream from server, it is invalid
regardless stream ID is even or odd. This is because client is
not expected to receive request from server. */
if (!session->server &&
session_detect_idle_stream(session, frame->hd.stream_id)) {
return session_inflate_handle_invalid_connection(
session, frame, NGHTTP2_PROTOCOL_ERROR,
"request HEADERS: client received request");
}
if (!session_is_new_peer_stream_id(session, frame->hd.stream_id)) {
/* The spec says if an endpoint receives a HEADERS with invalid
stream ID, it MUST issue connection error with error code
......
......@@ -1767,6 +1767,58 @@ void test_nghttp2_session_on_request_headers_received(void) {
nghttp2_frame_headers_free(&frame.headers);
nghttp2_session_del(session);
/* Check client side */
nghttp2_session_client_new(&session, &callbacks, &user_data);
/* Receiving peer's idle stream ID is subject to connection error */
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_request_headers_received(session, &frame));
CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_FAIL_ON_SEND);
nghttp2_frame_headers_free(&frame.headers);
nghttp2_session_del(session);
nghttp2_session_client_new(&session, &callbacks, &user_data);
/* Receiving our's idle stream ID is subject to connection error */
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_request_headers_received(session, &frame));
CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_FAIL_ON_SEND);
nghttp2_frame_headers_free(&frame.headers);
nghttp2_session_del(session);
nghttp2_session_client_new(&session, &callbacks, &user_data);
session->next_stream_id = 5;
/* Stream ID which is not idle and not in stream map is just
ignored */
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_request_headers_received(session, &frame));
CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_FAIL_ON_SEND));
nghttp2_frame_headers_free(&frame.headers);
nghttp2_session_del(session);
}
void test_nghttp2_session_on_response_headers_received(void) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment