diff --git a/rust/src/http2/http2.rs b/rust/src/http2/http2.rs index 99a8d16a1c..3cbbf1d2b3 100644 --- a/rust/src/http2/http2.rs +++ b/rust/src/http2/http2.rs @@ -221,7 +221,7 @@ impl HTTP2Transaction { STREAM_TOCLIENT, "content-range", ) { - match range::http2_parse_content_range(&value) { + match range::http2_parse_check_content_range(&value) { Ok((_, v)) => { range::http2_range_open(self, &v, flow, sfcm, flags, decompressed); if over && self.file_range != std::ptr::null_mut() { diff --git a/rust/src/http2/range.rs b/rust/src/http2/range.rs index 5533820905..08f3b5bec5 100644 --- a/rust/src/http2/range.rs +++ b/rust/src/http2/range.rs @@ -23,6 +23,8 @@ use crate::filecontainer::FileContainer; use crate::http2::http2::HTTP2Transaction; use nom::character::complete::digit1; +use nom::error::ErrorKind; +use nom::Err; use nom::IResult; use std::os::raw::c_uchar; use std::str::FromStr; @@ -68,7 +70,7 @@ pub fn http2_parse_content_range_def<'a>(input: &'a [u8]) -> IResult<&'a [u8], H )); } -pub fn http2_parse_content_range<'a>(input: &'a [u8]) -> IResult<&'a [u8], HTTPContentRange> { +fn http2_parse_content_range<'a>(input: &'a [u8]) -> IResult<&'a [u8], HTTPContentRange> { let (i2, _) = take_while!(input, |c| c == b' ')?; let (i2, _) = take_till!(i2, |c| c == b' ')?; let (i2, _) = take_while!(i2, |c| c == b' ')?; @@ -78,6 +80,14 @@ pub fn http2_parse_content_range<'a>(input: &'a [u8]) -> IResult<&'a [u8], HTTPC ); } +pub fn http2_parse_check_content_range<'a>(input: &'a [u8]) -> IResult<&'a [u8], HTTPContentRange> { + let (rem, v) = http2_parse_content_range(input)?; + if v.start > v.end { + return Err(Err::Error((rem, ErrorKind::Verify))); + } + return Ok((rem, v)); +} + #[no_mangle] pub unsafe extern "C" fn rs_http_parse_content_range( cr: &mut HTTPContentRange, buffer: *const u8, buffer_len: u32, @@ -127,6 +137,13 @@ pub fn http2_range_open( tx: &mut HTTP2Transaction, v: &HTTPContentRange, flow: *const Flow, cfg: &'static SuricataFileContext, flags: u16, data: &[u8], ) { + if v.end <= 0 || v.size <= 0 { + // skipped for incomplete range information + return; + } else if v.end == v.size - 1 && v.start == 0 { + // whole file in one range + return; + } if let Ok((key, index)) = http2_range_key_get(tx) { let name = &key[index..]; tx.file_range = unsafe {