From a63ee5adbdbbd37387eda522f810ff6ebd5676ca Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Tue, 10 Nov 2020 10:21:32 +0100 Subject: [PATCH] http2: allow multiple size updates in one headers batch cf RFC 7541 section 4.2 --- rust/src/http2/http2.rs | 49 +++++++++++++++++++++++----------------- rust/src/http2/parser.rs | 4 ++-- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/rust/src/http2/http2.rs b/rust/src/http2/http2.rs index 8b4112ead6..6886dfff98 100644 --- a/rust/src/http2/http2.rs +++ b/rust/src/http2/http2.rs @@ -438,6 +438,31 @@ impl HTTP2State { } } + fn process_headers(&mut self, blocks: &Vec, dir: u8) { + let (mut update, mut sizeup) = (false, 0); + for i in 0..blocks.len() { + if blocks[i].error >= parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeError { + self.set_event(HTTP2Event::InvalidHeader); + } else if blocks[i].error + == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate + { + update = true; + if blocks[i].sizeupdate > sizeup { + sizeup = blocks[i].sizeupdate; + } + } + } + if update { + //borrow checker forbids to pass directly dyn_headers + let dyn_headers = if dir == STREAM_TOCLIENT { + &mut self.dynamic_headers_tc + } else { + &mut self.dynamic_headers_ts + }; + dyn_headers.max_size = sizeup as usize; + } + } + fn parse_frame_data( &mut self, ftype: u8, input: &[u8], complete: bool, hflags: u8, dir: u8, ) -> HTTP2FrameTypeData { @@ -573,13 +598,7 @@ impl HTTP2State { }; match parser::http2_parse_frame_push_promise(input, hflags, dyn_headers) { Ok((_, hs)) => { - for i in 0..hs.blocks.len() { - if hs.blocks[i].error - >= parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeError - { - self.set_event(HTTP2Event::InvalidHeader); - } - } + self.process_headers(&hs.blocks, dir); return HTTP2FrameTypeData::PUSHPROMISE(hs); } Err(nom::Err::Incomplete(_)) => { @@ -613,13 +632,7 @@ impl HTTP2State { }; match parser::http2_parse_frame_continuation(input, dyn_headers) { Ok((_, hs)) => { - for i in 0..hs.blocks.len() { - if hs.blocks[i].error - >= parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeError - { - self.set_event(HTTP2Event::InvalidHeader); - } - } + self.process_headers(&hs.blocks, dir); return HTTP2FrameTypeData::CONTINUATION(hs); } Err(nom::Err::Incomplete(_)) => { @@ -650,13 +663,7 @@ impl HTTP2State { }; match parser::http2_parse_frame_headers(input, hflags, dyn_headers) { Ok((hrem, hs)) => { - for i in 0..hs.blocks.len() { - if hs.blocks[i].error - >= parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeError - { - self.set_event(HTTP2Event::InvalidHeader); - } - } + self.process_headers(&hs.blocks, dir); if hrem.len() > 0 { SCLogDebug!("Remaining data for HTTP2 headers"); self.set_event(HTTP2Event::ExtraHeaderData); diff --git a/rust/src/http2/parser.rs b/rust/src/http2/parser.rs index 9ba2e5835d..61e4557f6a 100644 --- a/rust/src/http2/parser.rs +++ b/rust/src/http2/parser.rs @@ -562,9 +562,9 @@ fn http2_parse_headers_block_dynamic_size<'a>( )); } if (maxsize2 as usize) < dyn_headers.max_size { - dyn_headers.max_size = maxsize2 as usize; + //dyn_headers.max_size is updated later with all headers //may evict entries - while dyn_headers.current_size > dyn_headers.max_size { + while dyn_headers.current_size > (maxsize2 as usize) { dyn_headers.current_size -= 32 + dyn_headers.table[0].name.len() + dyn_headers.table[0].value.len(); dyn_headers.table.remove(0);