From 2edba88a54609e9efe7a8ac81387c84cc41865dd Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Thu, 13 Aug 2026 19:06:47 +0000 Subject: [PATCH] http2: strip padding bytes from PADDED HEADERS/PUSH_PROMISE frames When the PADDED flag is set on HTTP/2 HEADERS or PUSH_PROMISE frames, the parser reads the 1-byte Pad Length field but never strips trailing padding bytes before passing the buffer to the HPACK decoder. Fix by stripping trailing padding before invoking the HPACK decoder. Ticket: #8787. --- rust/src/http2/parser.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/rust/src/http2/parser.rs b/rust/src/http2/parser.rs index 9f0d49a03c..527cd1be25 100644 --- a/rust/src/http2/parser.rs +++ b/rust/src/http2/parser.rs @@ -599,6 +599,14 @@ pub(super) fn get_frame_headers_hpack( flags & HTTP2_FLAG_HEADER_PRIORITY != 0, http2_parse_headers_priority, )(i2)?; + let i3 = if let Some(pl) = padlength { + if (pl as usize) > i3.len() { + return Err(Err::Error(make_error(input, ErrorKind::LengthValue))); + } + &i3[..i3.len() - pl as usize] + } else { + i3 + }; return Ok(( i3, HTTP2FrameHeaders { @@ -617,6 +625,14 @@ pub fn http2_parse_frame_headers<'a>( flags & HTTP2_FLAG_HEADER_PRIORITY != 0, http2_parse_headers_priority, )(i2)?; + let i3 = if let Some(pl) = padlength { + if (pl as usize) > i3.len() { + return Err(Err::Error(make_error(input, ErrorKind::LengthValue))); + } + &i3[..i3.len() - pl as usize] + } else { + i3 + }; let (i3, blocks) = http2_parse_headers_blocks(i3, dyn_headers)?; return Ok(( i3, @@ -641,6 +657,14 @@ pub fn http2_parse_frame_push_promise<'a>( ) -> IResult<&'a [u8], HTTP2FramePushPromise> { let (i2, padlength) = cond(flags & HTTP2_FLAG_HEADER_PADDED != 0, be_u8)(input)?; let (i3, stream_id) = bits(tuple((take_bits(1u8), take_bits(31u32))))(i2)?; + let i3 = if let Some(pl) = padlength { + if (pl as usize) > i3.len() { + return Err(Err::Error(make_error(input, ErrorKind::LengthValue))); + } + &i3[..i3.len() - pl as usize] + } else { + i3 + }; let (i3, blocks) = http2_parse_headers_blocks(i3, dyn_headers)?; return Ok(( i3,