From deb390cf858f4a5c31b9a69630478762041bde64 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 11 Jan 2022 19:50:45 +0900 Subject: [PATCH] Fix decoder table size update When applying new header table size acknowledged with SETTINGS ACK by an encoder, change the header table size on a decoder only when it strictly lowers the current maximum table size set by Dynamic Table Size Update from the encoder or the default size 4096 if no Dynamic Table Size Update is received. Previously, the header table size on a decoder is always changed. If a maximum size in SETTINGS are increased (e.g., 4096 -> 8192), and then decreased to the previous value, the decoder incorrectly requires Dynamic Table Size Update from an encoder. --- lib/nghttp2_hd.c | 11 ++++++----- tests/nghttp2_hd_test.c | 10 +++++----- tests/nghttp2_session_test.c | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/nghttp2_hd.c b/lib/nghttp2_hd.c index 5e869315..30ee9b88 100644 --- a/lib/nghttp2_hd.c +++ b/lib/nghttp2_hd.c @@ -1263,6 +1263,8 @@ int nghttp2_hd_inflate_change_table_size( return NGHTTP2_ERR_INVALID_STATE; } + inflater->settings_hd_table_bufsize_max = settings_max_dynamic_table_size; + /* It seems that encoder is not required to send dynamic table size update if the table size is not changed after applying SETTINGS_HEADER_TABLE_SIZE. RFC 7541 is ambiguous here, but this @@ -1275,13 +1277,12 @@ int nghttp2_hd_inflate_change_table_size( /* Remember minimum value, and validate that encoder sends the value less than or equal to this. */ inflater->min_hd_table_bufsize_max = settings_max_dynamic_table_size; + + inflater->ctx.hd_table_bufsize_max = settings_max_dynamic_table_size; + + hd_context_shrink_table_size(&inflater->ctx, NULL); } - inflater->settings_hd_table_bufsize_max = settings_max_dynamic_table_size; - - inflater->ctx.hd_table_bufsize_max = settings_max_dynamic_table_size; - - hd_context_shrink_table_size(&inflater->ctx, NULL); return 0; } diff --git a/tests/nghttp2_hd_test.c b/tests/nghttp2_hd_test.c index 74725d40..657d895f 100644 --- a/tests/nghttp2_hd_test.c +++ b/tests/nghttp2_hd_test.c @@ -734,7 +734,7 @@ void test_nghttp2_hd_change_table_size(void) { CU_ASSERT(4096 == deflater.ctx.hd_table_bufsize_max); - CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max); + CU_ASSERT(4096 == inflater.ctx.hd_table_bufsize_max); CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max); /* This will emit encoding context update with header table size 4096 */ @@ -830,8 +830,8 @@ void test_nghttp2_hd_change_table_size(void) { CU_ASSERT(8000 == deflater.ctx.hd_table_bufsize_max); CU_ASSERT(8000 == nghttp2_hd_deflate_get_max_dynamic_table_size(&deflater)); - CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max); - CU_ASSERT(8000 == nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater)); + CU_ASSERT(4096 == inflater.ctx.hd_table_bufsize_max); + CU_ASSERT(4096 == nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater)); CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max); rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2); @@ -856,8 +856,8 @@ void test_nghttp2_hd_change_table_size(void) { CU_ASSERT(8192 == deflater.ctx.hd_table_bufsize_max); CU_ASSERT(8192 == nghttp2_hd_deflate_get_max_dynamic_table_size(&deflater)); - CU_ASSERT(16383 == inflater.ctx.hd_table_bufsize_max); - CU_ASSERT(16383 == nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater)); + CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max); + CU_ASSERT(8000 == nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater)); CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max); rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2); diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 962e3c13..238ed905 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -5720,7 +5720,7 @@ void test_nghttp2_submit_settings(void) { nghttp2_frame_settings_free(&ack_frame.settings, mem); CU_ASSERT(16 * 1024 == session->local_settings.initial_window_size); - CU_ASSERT(1023 == session->hd_inflater.ctx.hd_table_bufsize_max); + CU_ASSERT(111 == session->hd_inflater.ctx.hd_table_bufsize_max); CU_ASSERT(111 == session->hd_inflater.min_hd_table_bufsize_max); CU_ASSERT(50 == session->local_settings.max_concurrent_streams);