diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index f8816400..82d4b2c0 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -1455,6 +1455,14 @@ static int session_headers_add_pad(nghttp2_session *session, return 0; } +static size_t session_estimate_headers_payload +(nghttp2_session *session, const nghttp2_nv *nva, size_t nvlen, + size_t additional) +{ + return nghttp2_hd_deflate_bound + (&session->hd_deflater, nva, nvlen) + additional; +} + /* * This function serializes frame for transmission. * @@ -1473,9 +1481,18 @@ static int session_prep_frame(nghttp2_session *session, switch(frame->hd.type) { case NGHTTP2_HEADERS: { nghttp2_headers_aux_data *aux_data; + size_t estimated_payloadlen; aux_data = (nghttp2_headers_aux_data*)item->aux_data; + estimated_payloadlen = session_estimate_headers_payload + (session, frame->headers.nva, frame->headers.nvlen, + NGHTTP2_PRIORITY_SPECLEN); + + if(estimated_payloadlen > NGHTTP2_MAX_HEADERSLEN) { + return NGHTTP2_ERR_FRAME_SIZE_ERROR; + } + if(frame->headers.cat == NGHTTP2_HCAT_REQUEST) { nghttp2_stream *stream; @@ -1589,9 +1606,17 @@ static int session_prep_frame(nghttp2_session *session, nghttp2_stream *stream; nghttp2_headers_aux_data *aux_data; nghttp2_priority_spec pri_spec; + size_t estimated_payloadlen; aux_data = (nghttp2_headers_aux_data*)item->aux_data; + estimated_payloadlen = session_estimate_headers_payload + (session, frame->push_promise.nva, frame->push_promise.nvlen, 0); + + if(estimated_payloadlen > NGHTTP2_MAX_HEADERSLEN) { + return NGHTTP2_ERR_FRAME_SIZE_ERROR; + } + rv = session_predicate_push_promise_send(session, frame->hd.stream_id); if(rv != 0) { return rv; diff --git a/tests/main.c b/tests/main.c index 042a86be..0fda14a1 100644 --- a/tests/main.c +++ b/tests/main.c @@ -124,8 +124,8 @@ int main(int argc, char* argv[]) test_nghttp2_session_send_headers_start_stream) || !CU_add_test(pSuite, "session_send_headers_reply", test_nghttp2_session_send_headers_reply) || - !CU_add_test(pSuite, "session_send_headers_header_comp_error", - test_nghttp2_session_send_headers_header_comp_error) || + !CU_add_test(pSuite, "session_send_headers_frame_size_error", + test_nghttp2_session_send_headers_frame_size_error) || !CU_add_test(pSuite, "session_send_headers_push_reply", test_nghttp2_session_send_headers_push_reply) || !CU_add_test(pSuite, "session_send_rst_stream", diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 29f0b652..308c3e1c 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -2383,7 +2383,7 @@ void test_nghttp2_session_send_headers_reply(void) nghttp2_session_del(session); } -void test_nghttp2_session_send_headers_header_comp_error(void) +void test_nghttp2_session_send_headers_frame_size_error(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; @@ -2394,6 +2394,7 @@ void test_nghttp2_session_send_headers_header_comp_error(void) nghttp2_nv nv[28]; size_t nnv = ARRLEN(nv); size_t i; + my_user_data ud; for(i = 0; i < nnv; ++i) { nv[i].name = (uint8_t*)"header"; @@ -2407,8 +2408,9 @@ void test_nghttp2_session_send_headers_header_comp_error(void) memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; + callbacks.on_frame_not_send_callback = on_frame_not_send_callback; - nghttp2_session_client_new(&session, &callbacks, NULL); + nghttp2_session_client_new(&session, &callbacks, &ud); nvlen = nnv; nghttp2_nv_array_copy(&nva, nv, nvlen); @@ -2419,10 +2421,14 @@ void test_nghttp2_session_send_headers_header_comp_error(void) session->next_stream_id += 2; nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL); + + ud.frame_not_send_cb_called = 0; + CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(session->goaway_flags & - (NGHTTP2_GOAWAY_SEND | NGHTTP2_GOAWAY_FAIL_ON_SEND)); + CU_ASSERT(1 == ud.frame_not_send_cb_called); + CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type); + CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR == ud.not_sent_error); for(i = 0; i < nnv; ++i) { free(nv[i].value); diff --git a/tests/nghttp2_session_test.h b/tests/nghttp2_session_test.h index c6e7f440..f9fbbd4f 100644 --- a/tests/nghttp2_session_test.h +++ b/tests/nghttp2_session_test.h @@ -52,7 +52,7 @@ void test_nghttp2_session_on_window_update_received(void); void test_nghttp2_session_on_data_received(void); void test_nghttp2_session_send_headers_start_stream(void); void test_nghttp2_session_send_headers_reply(void); -void test_nghttp2_session_send_headers_header_comp_error(void); +void test_nghttp2_session_send_headers_frame_size_error(void); void test_nghttp2_session_send_headers_push_reply(void); void test_nghttp2_session_send_rst_stream(void); void test_nghttp2_session_send_push_promise(void);