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.
This commit is contained in:
parent
babfa41424
commit
382a328ead
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue