From 1945d0f02ab3bda84411f1741ec4a54f507c8c6f Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 23 Jun 2015 23:03:54 +0900 Subject: [PATCH] Fix assertion failure in nghttp2_stream.c This is regression introduced in 46b70c1db8534a2d3ee8dc93eb6343633a0180b3. --- lib/nghttp2_stream.c | 7 ++++++- tests/main.c | 2 ++ tests/nghttp2_session_test.c | 39 ++++++++++++++++++++++++++++++++++++ tests/nghttp2_session_test.h | 1 + 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/lib/nghttp2_stream.c b/lib/nghttp2_stream.c index d237d2fa..fae02292 100644 --- a/lib/nghttp2_stream.c +++ b/lib/nghttp2_stream.c @@ -356,7 +356,12 @@ static int stream_update_dep_on_detach_item(nghttp2_stream *stream, return 0; } - assert(stream->dpri == NGHTTP2_STREAM_DPRI_TOP); + if (stream->dpri == NGHTTP2_STREAM_DPRI_NO_ITEM) { + /* nghttp2_stream_defer_item() does not clear stream->item, but + set dpri = NGHTTP2_STREAM_DPRI_NO_ITEM. Catch this case + here. */ + return 0; + } stream->dpri = NGHTTP2_STREAM_DPRI_NO_ITEM; diff --git a/tests/main.c b/tests/main.c index d15e3c13..7353ad74 100644 --- a/tests/main.c +++ b/tests/main.c @@ -266,6 +266,8 @@ int main(int argc _U_, char *argv[] _U_) { test_nghttp2_session_send_data_callback) || !CU_add_test(pSuite, "session_on_begin_headers_temporal_failure", test_nghttp2_session_on_begin_headers_temporal_failure) || + !CU_add_test(pSuite, "session_defer_then_close", + test_nghttp2_session_defer_then_close) || !CU_add_test(pSuite, "http_mandatory_headers", test_nghttp2_http_mandatory_headers) || !CU_add_test(pSuite, "http_content_length", diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 39cf8654..157a81ed 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -7469,6 +7469,45 @@ void test_nghttp2_session_on_begin_headers_temporal_failure(void) { nghttp2_bufs_free(&bufs); } +void test_nghttp2_session_defer_then_close(void) { + nghttp2_session *session; + nghttp2_session_callbacks callbacks; + nghttp2_data_provider prd; + int rv; + const uint8_t *datap; + ssize_t datalen; + nghttp2_frame frame; + + memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); + callbacks.send_callback = null_send_callback; + + nghttp2_session_client_new(&session, &callbacks, NULL); + + prd.read_callback = defer_data_source_read_callback; + + rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), &prd, NULL); + CU_ASSERT(rv > 0); + + /* This sends HEADERS */ + datalen = nghttp2_session_mem_send(session, &datap); + + CU_ASSERT(datalen > 0); + + /* This makes DATA item deferred */ + datalen = nghttp2_session_mem_send(session, &datap); + + CU_ASSERT(datalen == 0); + + nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL); + + /* Assertion failure; GH-264 */ + rv = nghttp2_session_on_rst_stream_received(session, &frame); + + CU_ASSERT(rv == 0); + + nghttp2_session_del(session); +} + static void check_nghttp2_http_recv_headers_fail( nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id, int stream_state, const nghttp2_nv *nva, size_t nvlen) { diff --git a/tests/nghttp2_session_test.h b/tests/nghttp2_session_test.h index 3b4b2b5d..b93d848e 100644 --- a/tests/nghttp2_session_test.h +++ b/tests/nghttp2_session_test.h @@ -126,6 +126,7 @@ void test_nghttp2_session_cancel_reserved_remote(void); void test_nghttp2_session_reset_pending_headers(void); void test_nghttp2_session_send_data_callback(void); void test_nghttp2_session_on_begin_headers_temporal_failure(void); +void test_nghttp2_session_defer_then_close(void); void test_nghttp2_http_mandatory_headers(void); void test_nghttp2_http_content_length(void); void test_nghttp2_http_content_length_mismatch(void);