detect/integers: index or_absent and or_oob

To match if array is empty, or index is out of bounds
pull/13878/head
Philippe Antoine 2 months ago committed by Victor Julien
parent 1480cf47ab
commit 82f0e725a2

@ -110,8 +110,10 @@ They expand the syntax of a single integer::
all Match only if all indexes match all Match only if all indexes match
all1 Match only if all and at least one indexes match all1 Match only if all and at least one indexes match
nb Matches a number of times nb Matches a number of times
or_absent Match with any index or no values
0>= Match specific index 0>= Match specific index
0< Match specific index with back to front indexing 0< Match specific index with back to front indexing
oob_or Match with specific index or index out of bounds
========= ================================================ ========= ================================================
The index ``all`` will match if there is no value. The index ``all`` will match if there is no value.

@ -55,7 +55,8 @@ pub enum DetectUintIndex {
Any, Any,
All, All,
All1, All1,
Index(i32), OrAbsent,
Index((bool, i32)),
NumberMatches(DetectUintData<u32>), NumberMatches(DetectUintData<u32>),
} }
@ -66,12 +67,15 @@ pub struct DetectUintArrayData<T> {
} }
fn parse_uint_index_precise(s: &str) -> IResult<&str, DetectUintIndex> { fn parse_uint_index_precise(s: &str) -> IResult<&str, DetectUintIndex> {
let (s, oob) = opt(tag("oob_or"))(s)?;
let (s, _) = opt(is_a(" "))(s)?;
let (s, i32_index) = nom_i32(s)?; let (s, i32_index) = nom_i32(s)?;
Ok((s, DetectUintIndex::Index(i32_index))) Ok((s, DetectUintIndex::Index((oob.is_some(), i32_index))))
} }
fn parse_uint_index_nb(s: &str) -> IResult<&str, DetectUintIndex> { fn parse_uint_index_nb(s: &str) -> IResult<&str, DetectUintIndex> {
let (s, _) = tag("nb")(s)?; let (s, _) = tag("nb")(s)?;
let (s, _) = opt(is_a(" "))(s)?;
let (s, du32) = detect_parse_uint::<u32>(s)?; let (s, du32) = detect_parse_uint::<u32>(s)?;
Ok((s, DetectUintIndex::NumberMatches(du32))) Ok((s, DetectUintIndex::NumberMatches(du32)))
} }
@ -87,6 +91,7 @@ fn parse_uint_index(parts: &[&str]) -> Option<DetectUintIndex> {
"all" => DetectUintIndex::All, "all" => DetectUintIndex::All,
"all1" => DetectUintIndex::All1, "all1" => DetectUintIndex::All1,
"any" => DetectUintIndex::Any, "any" => DetectUintIndex::Any,
"or_absent" => DetectUintIndex::OrAbsent,
// not only a literal, but some numeric value // not only a literal, but some numeric value
_ => return parse_uint_index_val(parts[1]), _ => return parse_uint_index_val(parts[1]),
} }
@ -136,6 +141,21 @@ pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
} }
return 0; return 0;
} }
DetectUintIndex::OrAbsent => {
let mut has_elem = false;
for response in array {
if let Some(code) = get_value(response) {
if detect_match_uint::<U>(&ctx.du, code) {
return 1;
}
has_elem = true;
}
}
if !has_elem && eof {
return 1;
}
return 0;
}
DetectUintIndex::NumberMatches(du32) => { DetectUintIndex::NumberMatches(du32) => {
if !eof { if !eof {
match du32.mode { match du32.mode {
@ -189,7 +209,7 @@ pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
} }
return 0; return 0;
} }
DetectUintIndex::Index(idx) => { DetectUintIndex::Index((oob, idx)) => {
let index = if *idx < 0 { let index = if *idx < 0 {
// negative values for backward indexing. // negative values for backward indexing.
((array.len() as i32) + idx) as usize ((array.len() as i32) + idx) as usize
@ -197,6 +217,9 @@ pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
*idx as usize *idx as usize
}; };
if array.len() <= index { if array.len() <= index {
if *oob && eof {
return 1;
}
return 0; return 0;
} }
if let Some(code) = get_value(&array[index]) { if let Some(code) = get_value(&array[index]) {

Loading…
Cancel
Save