Version in base suite: 1.64.0-1.1 Base version: nghttp2_1.64.0-1.1 Target version: nghttp2_1.64.0-1.1+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/n/nghttp2/nghttp2_1.64.0-1.1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/n/nghttp2/nghttp2_1.64.0-1.1+deb13u1.dsc changelog | 9 patches/CVE-2026-27135-test.patch | 503 ++++++++++++++++++++++++++++++++++++++ patches/CVE-2026-27135.patch | 102 +++++++ patches/series | 2 4 files changed, 616 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpe7egzlsh/nghttp2_1.64.0-1.1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpe7egzlsh/nghttp2_1.64.0-1.1+deb13u1.dsc: no acceptable signature found diff -Nru nghttp2-1.64.0/debian/changelog nghttp2-1.64.0/debian/changelog --- nghttp2-1.64.0/debian/changelog 2025-04-11 15:50:32.000000000 +0000 +++ nghttp2-1.64.0/debian/changelog 2026-04-15 15:04:15.000000000 +0000 @@ -1,3 +1,12 @@ +nghttp2 (1.64.0-1.1+deb13u1) trixie-security; urgency=medium + + * Non-maintainer upload by the Security Team. + * CVE-2026-27135 (Closes: #1131369) + Fix missing iframe->state validations to avoid assertion failure. + * Add test for CVE-2026-27135 (cherry-picked from upstream c619c7b) + + -- Lukas Märdian Wed, 15 Apr 2026 17:04:15 +0200 + nghttp2 (1.64.0-1.1) unstable; urgency=medium * Add patch: lp-2104171-avoid-rubydomain-namespace.patch (Closes: #1095360) diff -Nru nghttp2-1.64.0/debian/patches/CVE-2026-27135-test.patch nghttp2-1.64.0/debian/patches/CVE-2026-27135-test.patch --- nghttp2-1.64.0/debian/patches/CVE-2026-27135-test.patch 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-1.64.0/debian/patches/CVE-2026-27135-test.patch 2026-04-15 15:04:15.000000000 +0000 @@ -0,0 +1,503 @@ +From: Tatsuhiro Tsujikawa +Date: Wed, 18 Feb 2026 20:47:36 +0900 +Subject: Add tests for iframe->state validation + +Backport: The upstream test from commit c619c7b was written for a newer +nghttp2 version where pending_no_rfc7540_priorities does not exist anymore. +Here, it defaults to UINT8_MAX, which causes +session_no_rfc7540_pri_no_fallback() to return false. This makes the +PRIORITY_UPDATE frame get silently ignored (routed to IB_IGN_PAYLOAD) instead +of being processed through session_process_priority_update_frame(). The +on_frame_recv_callback never fires, terminate_session() is never called, and +session_inbound_frame_reset() resets the state to IB_READ_HEAD (2) instead of +preserving IB_IGN_ALL (15). Therefore, we added +session->pending_no_rfc7540_priorities = 1; after creating the server session +in both PRIORITY_UPDATE sub-tests so the frame is actually processed. + +Origin: backport, https://github.com/nghttp2/nghttp2/commit/c619c7be0737ac78051b1cacf4b1ce5467eb838d +--- + tests/nghttp2_session_test.c | 447 +++++++++++++++++++++++++++++++++++++++++++ + tests/nghttp2_session_test.h | 1 + + 2 files changed, 448 insertions(+) + +diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c +index 3cb8f24..a0f4c49 100644 +--- a/tests/nghttp2_session_test.c ++++ b/tests/nghttp2_session_test.c +@@ -181,6 +181,7 @@ static const MunitTest tests[] = { + munit_void_test(test_nghttp2_session_no_rfc7540_priorities), + munit_void_test(test_nghttp2_session_server_fallback_rfc7540_priorities), + munit_void_test(test_nghttp2_session_stream_reset_ratelim), ++ munit_void_test(test_nghttp2_session_verify_iframe_state), + munit_void_test(test_nghttp2_http_mandatory_headers), + munit_void_test(test_nghttp2_http_content_length), + munit_void_test(test_nghttp2_http_content_length_mismatch), +@@ -12418,6 +12419,456 @@ void test_nghttp2_session_stream_reset_ratelim(void) { + nghttp2_option_del(option); + } + ++static int term_session_on_invalid_frame_recv_callback( ++ nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code, ++ void *user_data) { ++ int rv; ++ (void)frame; ++ (void)lib_error_code; ++ (void)user_data; ++ ++ rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR); ++ ++ assert_int(0, ==, rv); ++ ++ return 0; ++} ++ ++static int term_session_on_begin_frame_callback(nghttp2_session *session, ++ const nghttp2_frame_hd *hd, ++ void *user_data) { ++ int rv; ++ (void)hd; ++ (void)user_data; ++ ++ rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR); ++ ++ assert_int(0, ==, rv); ++ ++ return 0; ++} ++ ++static int term_session_on_frame_recv_callback(nghttp2_session *session, ++ const nghttp2_frame *frame, ++ void *user_data) { ++ int rv; ++ (void)frame; ++ (void)user_data; ++ ++ rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR); ++ ++ assert_int(0, ==, rv); ++ ++ return 0; ++} ++ ++static int term_session_on_data_chunk_recv_callback( ++ nghttp2_session *session, uint8_t flags, int32_t stream_id, ++ const uint8_t *data, size_t len, void *user_data) { ++ int rv; ++ (void)flags; ++ (void)stream_id; ++ (void)data; ++ (void)len; ++ (void)user_data; ++ ++ rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR); ++ ++ assert_int(0, ==, rv); ++ ++ return 0; ++} ++ ++static int term_session_unpack_extension_callback(nghttp2_session *session, ++ void **payload, ++ const nghttp2_frame_hd *hd, ++ void *user_data) { ++ int rv; ++ (void)payload; ++ (void)hd; ++ (void)user_data; ++ ++ rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR); ++ ++ assert_int(0, ==, rv); ++ ++ return 0; ++} ++ ++static int term_session_on_extension_chunk_recv_callback( ++ nghttp2_session *session, const nghttp2_frame_hd *hd, const uint8_t *data, ++ size_t len, void *user_data) { ++ int rv; ++ (void)hd; ++ (void)data; ++ (void)len; ++ (void)user_data; ++ ++ rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR); ++ ++ assert_int(0, ==, rv); ++ ++ return NGHTTP2_ERR_CANCEL; ++} ++ ++void test_nghttp2_session_verify_iframe_state(void) { ++ nghttp2_session *session; ++ nghttp2_session_callbacks callbacks; ++ nghttp2_bufs bufs; ++ nghttp2_buf *buf; ++ nghttp2_frame frame; ++ nghttp2_extension extfr; ++ nghttp2_ext_priority_update priority_update; ++ nghttp2_ext_altsvc altsvc; ++ nghttp2_frame_hd hd; ++ uint8_t size_err_hd[NGHTTP2_FRAME_HDLEN]; ++ nghttp2_ssize rv; ++ const char field_value[] = "i"; ++ nghttp2_option *option; ++ nghttp2_hd_deflater deflater; ++ size_t nvlen; ++ nghttp2_nv *nva; ++ nghttp2_mem *mem = nghttp2_mem_default(); ++ my_user_data ud; ++ nghttp2_buf udbuf; ++ const char uddata[] = "hello world"; ++ ++ nghttp2_frame_hd_init(&hd, 0, NGHTTP2_RST_STREAM, NGHTTP2_FLAG_NONE, 1); ++ nghttp2_frame_pack_frame_hd(size_err_hd, &hd); ++ ++ nghttp2_buf_init2(&ud.scratchbuf, 4096, mem); ++ nghttp2_buf_init2(&udbuf, 4096, mem); ++ ++ nghttp2_frame_hd_init(&hd, sizeof(uddata) - 1, 111, 0xab, 1000000007); ++ nghttp2_frame_pack_frame_hd(udbuf.last, &hd); ++ udbuf.last += NGHTTP2_FRAME_HDLEN; ++ udbuf.last = nghttp2_cpymem(udbuf.last, uddata, sizeof(uddata) - 1); ++ ++ nghttp2_option_new(&option); ++ nghttp2_option_set_builtin_recv_extension_type(option, ++ NGHTTP2_PRIORITY_UPDATE); ++ nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC); ++ nghttp2_option_set_user_recv_extension_type(option, 111); ++ ++ frame_pack_bufs_init(&bufs); ++ ++ /* ALTSVC + on_invalid_frame_recv_callback + FRAME_SIZE_ERROR */ ++ memset(&callbacks, 0, sizeof(callbacks)); ++ callbacks.on_invalid_frame_recv_callback = ++ term_session_on_invalid_frame_recv_callback; ++ ++ nghttp2_session_client_new2(&session, &callbacks, NULL, option); ++ ++ extfr.payload = &altsvc; ++ nghttp2_frame_altsvc_init(&extfr, 0, NULL, 0, NULL, 0); ++ nghttp2_bufs_reset(&bufs); ++ nghttp2_frame_pack_altsvc(&bufs, &extfr); ++ ++ buf = &bufs.head->buf; ++ ++ rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs)); ++ ++ assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd)); ++ ++ assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ nghttp2_session_del(session); ++ ++ /* HEADERS + on_begin_frame_callback + FRAME_SIZE_ERROR */ ++ memset(&callbacks, 0, sizeof(callbacks)); ++ callbacks.on_begin_frame_callback = term_session_on_begin_frame_callback; ++ ++ nghttp2_session_server_new(&session, &callbacks, NULL); ++ ++ nvlen = ARRLEN(reqnv); ++ nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem); ++ nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, ++ NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen); ++ nghttp2_hd_deflate_init(&deflater, mem); ++ nghttp2_bufs_reset(&bufs); ++ rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); ++ ++ assert_ptrdiff(0, ==, rv); ++ ++ nghttp2_frame_headers_free(&frame.headers, mem); ++ ++ buf = &bufs.head->buf; ++ ++ rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs)); ++ ++ assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd)); ++ ++ assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ nghttp2_hd_deflate_free(&deflater); ++ nghttp2_session_del(session); ++ ++ /* Any frame (other than HEADERS) + on_begin_frame_callback + ++ FRAME_SIZE_ERROR */ ++ memset(&callbacks, 0, sizeof(callbacks)); ++ callbacks.on_begin_frame_callback = term_session_on_begin_frame_callback; ++ ++ nghttp2_session_server_new(&session, &callbacks, NULL); ++ ++ nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_NO_ERROR); ++ nghttp2_bufs_reset(&bufs); ++ nghttp2_frame_pack_rst_stream(&bufs, &frame.rst_stream); ++ ++ buf = &bufs.head->buf; ++ ++ rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs)); ++ ++ assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd)); ++ ++ assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ nghttp2_session_del(session); ++ ++ /* PRIORITY_UPDATE + on_frame_recv_callback + FRAME_SIZE_ERROR */ ++ memset(&callbacks, 0, sizeof(callbacks)); ++ callbacks.on_frame_recv_callback = term_session_on_frame_recv_callback; ++ ++ nghttp2_session_server_new2(&session, &callbacks, NULL, option); ++ ++ session->pending_no_rfc7540_priorities = 1; ++ ++ extfr.payload = &priority_update; ++ nghttp2_frame_priority_update_init(&extfr, 1, (uint8_t *)field_value, ++ sizeof(field_value) - 1); ++ nghttp2_bufs_reset(&bufs); ++ nghttp2_frame_pack_priority_update(&bufs, &extfr); ++ ++ buf = &bufs.head->buf; ++ ++ rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs)); ++ ++ assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd)); ++ ++ assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ nghttp2_session_del(session); ++ ++ /* ALTSVC + on_frame_recv_callback + FRAME_SIZE_ERROR */ ++ memset(&callbacks, 0, sizeof(callbacks)); ++ callbacks.on_frame_recv_callback = term_session_on_frame_recv_callback; ++ ++ nghttp2_session_client_new2(&session, &callbacks, NULL, option); ++ ++ extfr.payload = &altsvc; ++ nghttp2_frame_altsvc_init(&extfr, 0, (uint8_t *)"nghttp2.org", ++ sizeof("nghttp2.org") - 1, (uint8_t *)"h2", ++ sizeof("h2") - 1); ++ nghttp2_bufs_reset(&bufs); ++ nghttp2_frame_pack_altsvc(&bufs, &extfr); ++ ++ buf = &bufs.head->buf; ++ ++ rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs)); ++ ++ assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd)); ++ ++ assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ nghttp2_session_del(session); ++ ++ /* user-defined extension frame + on_frame_recv_callback + ++ FRAME_SIZE_ERROR */ ++ memset(&callbacks, 0, sizeof(callbacks)); ++ callbacks.on_frame_recv_callback = term_session_on_frame_recv_callback; ++ callbacks.unpack_extension_callback = unpack_extension_callback; ++ ++ nghttp2_session_server_new2(&session, &callbacks, &ud, option); ++ ++ nghttp2_buf_reset(&ud.scratchbuf); ++ ++ rv = nghttp2_session_mem_recv2(session, udbuf.pos, nghttp2_buf_len(&udbuf)); ++ ++ assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&udbuf), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd)); ++ ++ assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ nghttp2_session_del(session); ++ ++ /* DATA + on_data_chunk_recv_callback + FRAME_SIZE_ERROR*/ ++ memset(&callbacks, 0, sizeof(callbacks)); ++ callbacks.on_data_chunk_recv_callback = ++ term_session_on_data_chunk_recv_callback; ++ ++ nghttp2_session_server_new(&session, &callbacks, NULL); ++ ++ nvlen = ARRLEN(reqnv); ++ nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem); ++ nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, ++ NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen); ++ nghttp2_hd_deflate_init(&deflater, mem); ++ nghttp2_bufs_reset(&bufs); ++ rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); ++ ++ assert_ptrdiff(0, ==, rv); ++ ++ nghttp2_frame_headers_free(&frame.headers, mem); ++ ++ buf = &bufs.head->buf; ++ ++ rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs)); ++ ++ assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_READ_HEAD, ==, ++ session->iframe.state); ++ ++ nghttp2_frame_hd_init(&hd, 10, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1); ++ nghttp2_bufs_reset(&bufs); ++ nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd); ++ bufs.head->buf.last += NGHTTP2_FRAME_HDLEN; ++ memset(bufs.head->buf.last, 0, 10); ++ bufs.head->buf.last += 10; ++ ++ buf = &bufs.head->buf; ++ ++ rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs)); ++ ++ assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd)); ++ ++ assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ nghttp2_hd_deflate_free(&deflater); ++ nghttp2_session_del(session); ++ ++ /* user-defined extension frame + on_extension_chunk_recv_callback + ++ FRAME_SIZE_ERROR */ ++ memset(&callbacks, 0, sizeof(callbacks)); ++ callbacks.on_extension_chunk_recv_callback = ++ term_session_on_extension_chunk_recv_callback; ++ callbacks.unpack_extension_callback = unpack_extension_callback; ++ ++ nghttp2_session_server_new2(&session, &callbacks, &ud, option); ++ ++ nghttp2_buf_reset(&ud.scratchbuf); ++ ++ rv = nghttp2_session_mem_recv2(session, udbuf.pos, nghttp2_buf_len(&udbuf)); ++ ++ assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&udbuf), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd)); ++ ++ assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ nghttp2_session_del(session); ++ ++ /* user-defined extension frame + unpack_extension_callback + ++ FRAME_SIZE_ERROR */ ++ memset(&callbacks, 0, sizeof(callbacks)); ++ callbacks.unpack_extension_callback = term_session_unpack_extension_callback; ++ ++ nghttp2_session_server_new2(&session, &callbacks, &ud, option); ++ ++ nghttp2_buf_reset(&ud.scratchbuf); ++ ++ rv = nghttp2_session_mem_recv2(session, udbuf.pos, nghttp2_buf_len(&udbuf)); ++ ++ assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&udbuf), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd)); ++ ++ assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ nghttp2_session_del(session); ++ ++ /* PRIORITY_UPDATE on stream 1 + FRAME_SIZE_ERROR */ ++ memset(&callbacks, 0, sizeof(callbacks)); ++ ++ nghttp2_session_server_new2(&session, &callbacks, NULL, option); ++ ++ session->pending_no_rfc7540_priorities = 1; ++ ++ extfr.payload = &priority_update; ++ nghttp2_frame_priority_update_init(&extfr, 1, (uint8_t *)field_value, ++ sizeof(field_value) - 1); ++ nghttp2_bufs_reset(&bufs); ++ nghttp2_frame_pack_priority_update(&bufs, &extfr); ++ buf = &bufs.head->buf; ++ /* Set invalid stream ID 1 */ ++ buf->pos[5 + sizeof(uint32_t) - 1] = 1; ++ ++ rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs)); ++ ++ assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ rv = nghttp2_session_mem_recv2(session, size_err_hd, sizeof(size_err_hd)); ++ ++ assert_ptrdiff((nghttp2_ssize)sizeof(size_err_hd), ==, rv); ++ assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==, ++ session->iframe.state); ++ ++ nghttp2_session_del(session); ++ ++ nghttp2_buf_free(&udbuf, mem); ++ nghttp2_buf_free(&ud.scratchbuf, mem); ++ nghttp2_bufs_free(&bufs); ++ nghttp2_option_del(option); ++} ++ ++typedef struct check_http_opts { ++ int server; ++ int connect_protocol; ++} check_http_opts; ++ ++static void check_http_opts_reset(check_http_opts *opts) { ++ memset(opts, 0, sizeof(*opts)); ++} ++ + 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 89e8575..1fe9628 100644 +--- a/tests/nghttp2_session_test.h ++++ b/tests/nghttp2_session_test.h +@@ -177,6 +177,7 @@ munit_void_test_decl(test_nghttp2_session_set_stream_user_data) + munit_void_test_decl(test_nghttp2_session_no_rfc7540_priorities) + munit_void_test_decl(test_nghttp2_session_server_fallback_rfc7540_priorities) + munit_void_test_decl(test_nghttp2_session_stream_reset_ratelim) ++munit_void_test_decl(test_nghttp2_session_verify_iframe_state) + munit_void_test_decl(test_nghttp2_http_mandatory_headers) + munit_void_test_decl(test_nghttp2_http_content_length) + munit_void_test_decl(test_nghttp2_http_content_length_mismatch) diff -Nru nghttp2-1.64.0/debian/patches/CVE-2026-27135.patch nghttp2-1.64.0/debian/patches/CVE-2026-27135.patch --- nghttp2-1.64.0/debian/patches/CVE-2026-27135.patch 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-1.64.0/debian/patches/CVE-2026-27135.patch 2026-04-15 15:04:15.000000000 +0000 @@ -0,0 +1,102 @@ +From: Tatsuhiro Tsujikawa +Date: Wed, 18 Feb 2026 18:04:30 +0900 +Subject: Fix missing iframe->state validations to avoid assertion failure + +Origin: upstream, https://github.com/nghttp2/nghttp2/commit/5c7df8fa815ac1004d9ecb9d1f7595c4d37f46e1 +--- + lib/nghttp2_session.c | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c +index df33a89..396bcfc 100644 +--- a/lib/nghttp2_session.c ++++ b/lib/nghttp2_session.c +@@ -6063,6 +6063,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, + return rv; + } + ++ if (iframe->state == NGHTTP2_IB_IGN_ALL) { ++ return (nghttp2_ssize)inlen; ++ } ++ + on_begin_frame_called = 1; + + rv = session_process_headers_frame(session); +@@ -6429,6 +6433,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, + if (nghttp2_is_fatal(rv)) { + return rv; + } ++ ++ if (iframe->state == NGHTTP2_IB_IGN_ALL) { ++ return (nghttp2_ssize)inlen; ++ } + } + } + +@@ -6684,6 +6692,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, + return rv; + } + ++ if (iframe->state == NGHTTP2_IB_IGN_ALL) { ++ return (nghttp2_ssize)inlen; ++ } ++ + session_inbound_frame_reset(session); + + break; +@@ -6986,6 +6998,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, + if (nghttp2_is_fatal(rv)) { + return rv; + } ++ ++ if (iframe->state == NGHTTP2_IB_IGN_ALL) { ++ return (nghttp2_ssize)inlen; ++ } + } else { + iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; + } +@@ -7151,6 +7167,11 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, + rv = session->callbacks.on_data_chunk_recv_callback( + session, iframe->frame.hd.flags, iframe->frame.hd.stream_id, + in - readlen, (size_t)data_readlen, session->user_data); ++ ++ if (iframe->state == NGHTTP2_IB_IGN_ALL) { ++ return (nghttp2_ssize)inlen; ++ } ++ + if (rv == NGHTTP2_ERR_PAUSE) { + return (nghttp2_ssize)(in - first); + } +@@ -7237,6 +7258,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, + return rv; + } + ++ if (iframe->state == NGHTTP2_IB_IGN_ALL) { ++ return (nghttp2_ssize)inlen; ++ } ++ + if (rv != 0) { + busy = 1; + +@@ -7255,6 +7280,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, + return rv; + } + ++ if (iframe->state == NGHTTP2_IB_IGN_ALL) { ++ return (nghttp2_ssize)inlen; ++ } ++ + session_inbound_frame_reset(session); + + break; +@@ -7283,6 +7312,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, + return rv; + } + ++ if (iframe->state == NGHTTP2_IB_IGN_ALL) { ++ return (nghttp2_ssize)inlen; ++ } ++ + session_inbound_frame_reset(session); + + break; diff -Nru nghttp2-1.64.0/debian/patches/series nghttp2-1.64.0/debian/patches/series --- nghttp2-1.64.0/debian/patches/series 2025-04-11 15:50:32.000000000 +0000 +++ nghttp2-1.64.0/debian/patches/series 2026-04-15 15:04:15.000000000 +0000 @@ -1,3 +1,5 @@ 0002-Workaround-for-963648.patch 0002-add-munit-explicitly.patch lp-2104171-avoid-rubydomain-namespace.patch +CVE-2026-27135.patch +CVE-2026-27135-test.patch