detect/integers: count argument for multi-integers

Ticket: 7211

Allows to count the number of elements, without matching on
individual elements
pull/14055/head
Philippe Antoine 2 months ago committed by Victor Julien
parent 047f1c5080
commit 4b69a31dc3

@ -142,4 +142,17 @@ For the array [1,2,3,4,5,6], here are some examples:
* 3:-1 will have subslice [4,5]
* -4:4 will have subslice [3,4]
If one index is out of bounds, an empty subslice is used.
If one index is out of bounds, an empty subslice is used.
Count
-----
Multi-integer can also just count the number of occurences
without matching to a specific value.
The syntax is::
keyword: count [mode] value;
Examples::
http2.window:count >5;

@ -59,6 +59,7 @@ pub enum DetectUintIndex {
OrAbsent,
Index((bool, i32)),
NumberMatches(DetectUintData<u32>),
Count(DetectUintData<u32>),
}
#[derive(Debug, PartialEq)]
@ -112,6 +113,13 @@ fn parse_uint_subslice(parts: &[&str]) -> Option<(i32, i32)> {
return Some((start, end));
}
fn parse_uint_count(s: &str) -> IResult<&str, DetectUintData<u32>> {
let (s, _) = tag("count")(s)?;
let (s, _) = opt(is_a(" "))(s)?;
let (s, du32) = detect_parse_uint::<u32>(s)?;
Ok((s, du32))
}
fn parse_uint_index(parts: &[&str]) -> Option<DetectUintIndex> {
let index = if parts.len() >= 2 {
match parts[1] {
@ -122,6 +130,8 @@ fn parse_uint_index(parts: &[&str]) -> Option<DetectUintIndex> {
// not only a literal, but some numeric value
_ => return parse_uint_index_val(parts[1]),
}
} else if let Ok((_, du)) = parse_uint_count(parts[0]) {
DetectUintIndex::Count(du)
} else {
DetectUintIndex::Any
};
@ -136,6 +146,19 @@ pub(crate) fn detect_parse_array_uint<T: DetectIntType>(s: &str) -> Option<Detec
}
let index = parse_uint_index(&parts)?;
if let DetectUintIndex::Count(_) = &index {
return Some(DetectUintArrayData {
du: DetectUintData::<T> {
arg1: T::min_value(),
arg2: T::min_value(),
mode: DetectUintMode::DetectUintModeEqual,
},
index,
start: 0,
end: 0,
});
}
let (_, du) = detect_parse_uint::<T>(parts[0]).ok()?;
let (start, end) = parse_uint_subslice(&parts)?;
@ -157,6 +180,19 @@ pub(crate) fn detect_parse_array_uint_enum<T1: DetectIntType, T2: EnumString<T1>
}
let index = parse_uint_index(&parts)?;
if let DetectUintIndex::Count(_) = &index {
return Some(DetectUintArrayData {
du: DetectUintData::<T1> {
arg1: T1::min_value(),
arg2: T1::min_value(),
mode: DetectUintMode::DetectUintModeEqual,
},
index,
start: 0,
end: 0,
});
}
let du = detect_parse_uint_enum::<T1, T2>(parts[0])?;
let (start, end) = parse_uint_subslice(&parts)?;
@ -234,6 +270,26 @@ pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
}
return 0;
}
DetectUintIndex::Count(du32) => {
if !eof {
match du32.mode {
DetectUintMode::DetectUintModeGt | DetectUintMode::DetectUintModeGte => {}
_ => {
return 0;
}
}
}
let mut nb = 0u32;
for response in subslice {
if get_value(response).is_some() {
nb += 1;
}
}
if detect_match_uint(du32, nb) {
return 1;
}
return 0;
}
DetectUintIndex::All => {
if !eof {
return 0;

Loading…
Cancel
Save