Fix crash if response or data is submitted to closing stream
This commit is contained in:
parent
a152c6346d
commit
e66bd490a4
|
@ -1780,6 +1780,12 @@ static int session_prep_frame(nghttp2_session *session,
|
||||||
rv = session_predicate_headers_send(session, stream);
|
rv = session_predicate_headers_send(session, stream);
|
||||||
|
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
|
// If stream was alreay closed,
|
||||||
|
// nghttp2_session_get_stream() returns NULL, but item is
|
||||||
|
// still attached to the stream. Search stream including
|
||||||
|
// closed again.
|
||||||
|
stream =
|
||||||
|
nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
|
||||||
if (stream && stream->item == item) {
|
if (stream && stream->item == item) {
|
||||||
int rv2;
|
int rv2;
|
||||||
|
|
||||||
|
@ -1938,6 +1944,10 @@ static int session_prep_frame(nghttp2_session *session,
|
||||||
|
|
||||||
rv = nghttp2_session_predicate_data_send(session, stream);
|
rv = nghttp2_session_predicate_data_send(session, stream);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
|
// If stream was alreay closed, nghttp2_session_get_stream()
|
||||||
|
// returns NULL, but item is still attached to the stream.
|
||||||
|
// Search stream including closed again.
|
||||||
|
stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
|
||||||
if (stream) {
|
if (stream) {
|
||||||
int rv2;
|
int rv2;
|
||||||
|
|
||||||
|
|
|
@ -270,6 +270,8 @@ int main(int argc _U_, char *argv[] _U_) {
|
||||||
test_nghttp2_session_on_begin_headers_temporal_failure) ||
|
test_nghttp2_session_on_begin_headers_temporal_failure) ||
|
||||||
!CU_add_test(pSuite, "session_defer_then_close",
|
!CU_add_test(pSuite, "session_defer_then_close",
|
||||||
test_nghttp2_session_defer_then_close) ||
|
test_nghttp2_session_defer_then_close) ||
|
||||||
|
!CU_add_test(pSuite, "session_detach_item_from_closed_stream",
|
||||||
|
test_nghttp2_session_detach_item_from_closed_stream) ||
|
||||||
!CU_add_test(pSuite, "http_mandatory_headers",
|
!CU_add_test(pSuite, "http_mandatory_headers",
|
||||||
test_nghttp2_http_mandatory_headers) ||
|
test_nghttp2_http_mandatory_headers) ||
|
||||||
!CU_add_test(pSuite, "http_content_length",
|
!CU_add_test(pSuite, "http_content_length",
|
||||||
|
|
|
@ -7640,6 +7640,53 @@ void test_nghttp2_session_defer_then_close(void) {
|
||||||
nghttp2_session_del(session);
|
nghttp2_session_del(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int submit_response_on_stream_close(nghttp2_session *session,
|
||||||
|
int32_t stream_id,
|
||||||
|
uint32_t error_code _U_,
|
||||||
|
void *user_data _U_) {
|
||||||
|
nghttp2_data_provider data_prd;
|
||||||
|
data_prd.read_callback = temporal_failure_data_source_read_callback;
|
||||||
|
|
||||||
|
// Attempt to submit response or data to the stream being closed
|
||||||
|
switch (stream_id) {
|
||||||
|
case 1:
|
||||||
|
CU_ASSERT(0 == nghttp2_submit_response(session, stream_id, resnv,
|
||||||
|
ARRLEN(resnv), &data_prd));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, stream_id,
|
||||||
|
&data_prd));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_nghttp2_session_detach_item_from_closed_stream(void) {
|
||||||
|
nghttp2_session *session;
|
||||||
|
nghttp2_session_callbacks callbacks;
|
||||||
|
nghttp2_data_provider data_prd;
|
||||||
|
|
||||||
|
memset(&callbacks, 0, sizeof(callbacks));
|
||||||
|
|
||||||
|
callbacks.send_callback = null_send_callback;
|
||||||
|
callbacks.on_stream_close_callback = submit_response_on_stream_close;
|
||||||
|
|
||||||
|
data_prd.read_callback = temporal_failure_data_source_read_callback;
|
||||||
|
|
||||||
|
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||||
|
|
||||||
|
open_stream(session, 1);
|
||||||
|
open_stream(session, 3);
|
||||||
|
|
||||||
|
nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
|
||||||
|
nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
|
||||||
|
|
||||||
|
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||||
|
|
||||||
|
nghttp2_session_del(session);
|
||||||
|
}
|
||||||
|
|
||||||
static void check_nghttp2_http_recv_headers_fail(
|
static void check_nghttp2_http_recv_headers_fail(
|
||||||
nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
|
nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
|
||||||
int stream_state, const nghttp2_nv *nva, size_t nvlen) {
|
int stream_state, const nghttp2_nv *nva, size_t nvlen) {
|
||||||
|
|
|
@ -128,6 +128,7 @@ void test_nghttp2_session_reset_pending_headers(void);
|
||||||
void test_nghttp2_session_send_data_callback(void);
|
void test_nghttp2_session_send_data_callback(void);
|
||||||
void test_nghttp2_session_on_begin_headers_temporal_failure(void);
|
void test_nghttp2_session_on_begin_headers_temporal_failure(void);
|
||||||
void test_nghttp2_session_defer_then_close(void);
|
void test_nghttp2_session_defer_then_close(void);
|
||||||
|
void test_nghttp2_session_detach_item_from_closed_stream(void);
|
||||||
void test_nghttp2_http_mandatory_headers(void);
|
void test_nghttp2_http_mandatory_headers(void);
|
||||||
void test_nghttp2_http_content_length(void);
|
void test_nghttp2_http_content_length(void);
|
||||||
void test_nghttp2_http_content_length_mismatch(void);
|
void test_nghttp2_http_content_length_mismatch(void);
|
||||||
|
|
Loading…
Reference in New Issue