From f01161f5d137c3b124f7882fdec825b19a2dd6d5 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Fri, 1 Dec 2023 10:51:39 +0100 Subject: [PATCH 1/2] detect: integer keywords now support hexadecimal So that we can write enip.revision: 0x203 Ticket: 6645 --- rust/src/detect/uint.rs | 59 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/rust/src/detect/uint.rs b/rust/src/detect/uint.rs index 3d6a5baab0ca..77b24ca79c4b 100644 --- a/rust/src/detect/uint.rs +++ b/rust/src/detect/uint.rs @@ -17,7 +17,7 @@ use nom7::branch::alt; use nom7::bytes::complete::{is_a, tag, tag_no_case, take_while}; -use nom7::character::complete::digit1; +use nom7::character::complete::{digit1, hex_digit1}; use nom7::combinator::{all_consuming, map_opt, opt, value, verify}; use nom7::error::{make_error, ErrorKind}; use nom7::Err; @@ -73,8 +73,25 @@ pub fn detect_parse_uint_unit(i: &str) -> IResult<&str, u64> { return Ok((i, unit)); } +pub fn detect_parse_uint_value_hex(i: &str) -> IResult<&str, T> { + let (i, _) = tag("0x")(i)?; + let (i, arg1s) = hex_digit1(i)?; + match T::from_str_radix(arg1s, 16) { + Ok(arg1) => Ok((i, arg1)), + _ => Err(Err::Error(make_error(i, ErrorKind::Verify))), + } +} + +pub fn detect_parse_uint_value(i: &str) -> IResult<&str, T> { + let (i, arg1) = alt(( + detect_parse_uint_value_hex, + map_opt(digit1, |s: &str| s.parse::().ok()), + ))(i)?; + Ok((i, arg1)) +} + pub fn detect_parse_uint_with_unit(i: &str) -> IResult<&str, T> { - let (i, arg1) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; + let (i, arg1) = detect_parse_uint_value::(i)?; let (i, unit) = opt(detect_parse_uint_unit)(i)?; if arg1 >= T::one() { if let Some(u) = unit { @@ -107,11 +124,11 @@ pub fn detect_parse_uint_start_equal( pub fn detect_parse_uint_start_interval( i: &str, ) -> IResult<&str, DetectUintData> { - let (i, arg1) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; + let (i, arg1) = detect_parse_uint_value(i)?; let (i, _) = opt(is_a(" "))(i)?; let (i, _) = alt((tag("-"), tag("<>")))(i)?; let (i, _) = opt(is_a(" "))(i)?; - let (i, arg2) = verify(map_opt(digit1, |s: &str| s.parse::().ok()), |x| { + let (i, arg2) = verify(detect_parse_uint_value, |x| { x > &arg1 && *x - arg1 > T::one() })(i)?; Ok(( @@ -127,13 +144,13 @@ pub fn detect_parse_uint_start_interval( fn detect_parse_uint_start_interval_inclusive( i: &str, ) -> IResult<&str, DetectUintData> { - let (i, arg1) = verify(map_opt(digit1, |s: &str| s.parse::().ok()), |x| { + let (i, arg1) = verify(detect_parse_uint_value::, |x| { *x > T::min_value() })(i)?; let (i, _) = opt(is_a(" "))(i)?; let (i, _) = alt((tag("-"), tag("<>")))(i)?; let (i, _) = opt(is_a(" "))(i)?; - let (i, arg2) = verify(map_opt(digit1, |s: &str| s.parse::().ok()), |x| { + let (i, arg2) = verify(detect_parse_uint_value::, |x| { *x > arg1 && *x < T::max_value() })(i)?; Ok(( @@ -162,7 +179,7 @@ pub fn detect_parse_uint_mode(i: &str) -> IResult<&str, DetectUintMode> { fn detect_parse_uint_start_symbol(i: &str) -> IResult<&str, DetectUintData> { let (i, mode) = detect_parse_uint_mode(i)?; let (i, _) = opt(is_a(" "))(i)?; - let (i, arg1) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; + let (i, arg1) = detect_parse_uint_value(i)?; match mode { DetectUintMode::DetectUintModeNe => {} @@ -407,6 +424,34 @@ pub unsafe extern "C" fn rs_detect_u16_free(ctx: &mut DetectUintData) { mod tests { use super::*; + #[test] + fn test_parse_uint_hex() { + match detect_parse_uint::("0x100") { + Ok((_, val)) => { + assert_eq!(val.arg1, 0x100); + } + Err(_) => { + assert!(false); + } + } + match detect_parse_uint::("0xFF") { + Ok((_, val)) => { + assert_eq!(val.arg1, 255); + } + Err(_) => { + assert!(false); + } + } + match detect_parse_uint::("0xff") { + Ok((_, val)) => { + assert_eq!(val.arg1, 255); + } + Err(_) => { + assert!(false); + } + } + } + #[test] fn test_parse_uint_unit() { match detect_parse_uint::(" 2kb") { From aa0d56e12e1b8779e6e723a454598c4375d7f931 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Thu, 30 Nov 2023 15:18:20 +0100 Subject: [PATCH 2/2] detect: integer keywords now accept negated ranges Ticket: 6646 --- rust/src/detect/uint.rs | 42 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/rust/src/detect/uint.rs b/rust/src/detect/uint.rs index 77b24ca79c4b..cd22693ccc74 100644 --- a/rust/src/detect/uint.rs +++ b/rust/src/detect/uint.rs @@ -17,7 +17,7 @@ use nom7::branch::alt; use nom7::bytes::complete::{is_a, tag, tag_no_case, take_while}; -use nom7::character::complete::{digit1, hex_digit1}; +use nom7::character::complete::{char, digit1, hex_digit1}; use nom7::combinator::{all_consuming, map_opt, opt, value, verify}; use nom7::error::{make_error, ErrorKind}; use nom7::Err; @@ -35,6 +35,7 @@ pub enum DetectUintMode { DetectUintModeGte, DetectUintModeRange, DetectUintModeNe, + DetectUintModeNegRg, } #[derive(Debug)] @@ -124,6 +125,7 @@ pub fn detect_parse_uint_start_equal( pub fn detect_parse_uint_start_interval( i: &str, ) -> IResult<&str, DetectUintData> { + let (i, neg) = opt(char('!'))(i)?; let (i, arg1) = detect_parse_uint_value(i)?; let (i, _) = opt(is_a(" "))(i)?; let (i, _) = alt((tag("-"), tag("<>")))(i)?; @@ -131,12 +133,17 @@ pub fn detect_parse_uint_start_interval( let (i, arg2) = verify(detect_parse_uint_value, |x| { x > &arg1 && *x - arg1 > T::one() })(i)?; + let mode = if neg.is_some() { + DetectUintMode::DetectUintModeNegRg + } else { + DetectUintMode::DetectUintModeRange + }; Ok(( i, DetectUintData { arg1, arg2, - mode: DetectUintMode::DetectUintModeRange, + mode, }, )) } @@ -144,6 +151,7 @@ pub fn detect_parse_uint_start_interval( fn detect_parse_uint_start_interval_inclusive( i: &str, ) -> IResult<&str, DetectUintData> { + let (i, neg) = opt(char('!'))(i)?; let (i, arg1) = verify(detect_parse_uint_value::, |x| { *x > T::min_value() })(i)?; @@ -153,12 +161,17 @@ fn detect_parse_uint_start_interval_inclusive( let (i, arg2) = verify(detect_parse_uint_value::, |x| { *x > arg1 && *x < T::max_value() })(i)?; + let mode = if neg.is_some() { + DetectUintMode::DetectUintModeNegRg + } else { + DetectUintMode::DetectUintModeRange + }; Ok(( i, DetectUintData { arg1: arg1 - T::one(), arg2: arg2 + T::one(), - mode: DetectUintMode::DetectUintModeRange, + mode, }, )) } @@ -255,6 +268,11 @@ pub fn detect_match_uint(x: &DetectUintData, val: T) -> boo return true; } } + DetectUintMode::DetectUintModeNegRg => { + if val <= x.arg1 || val >= x.arg2 { + return true; + } + } } return false; } @@ -452,6 +470,24 @@ mod tests { } } + #[test] + fn test_parse_uint_negated_range() { + match detect_parse_uint::("!1-6") { + Ok((_, val)) => { + assert_eq!(val.arg1, 1); + assert_eq!(val.arg2, 6); + assert_eq!(val.mode, DetectUintMode::DetectUintModeNegRg); + assert!(detect_match_uint(&val, 1)); + assert!(!detect_match_uint(&val, 2)); + assert!(!detect_match_uint(&val, 5)); + assert!(detect_match_uint(&val, 6)); + } + Err(_) => { + assert!(false); + } + } + } + #[test] fn test_parse_uint_unit() { match detect_parse_uint::(" 2kb") {