Skip to content

Commit cb9ab95

Browse files
catenacybervictorjulien
authored andcommitted
detect/integers: subslice for multi-integers
1 parent 82f0e72 commit cb9ab95

2 files changed

Lines changed: 75 additions & 15 deletions

File tree

doc/userguide/rules/integer-keywords.rst

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ As :ref:`multi-buffers <rules-multi-buffer-matching>` and sticky buffers,
9898
some integer keywords are also multi-integer.
9999

100100
They expand the syntax of a single integer::
101-
keyword: operation and value[,index];
101+
keyword: operation and value[,index,subslice];
102102

103103
.. table:: **Index values for multi-integers keyword**
104104

@@ -124,4 +124,13 @@ be sure to have the final number of elements.
124124

125125
The index ``nb`` accepts all comparison modes as integer keywords.
126126
For example ``nb>3`` will match only if more than 3 integers in the
127-
array match the value.
127+
array match the value.
128+
129+
The subslice may use positive or negative indexing.
130+
For the array [1,2,3,4,5,6], here are some examples:
131+
* 2:4 will have subslice [3,4]
132+
* -4:-1 will have subslice [3,4,5]
133+
* 3:-1 will have subslice [4,5]
134+
* -4:4 will have subslice [3,4]
135+
136+
If one index is out of bounds, an empty subslice is used.

rust/src/detect/uint.rs

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ pub enum DetectUintIndex {
6464
pub struct DetectUintArrayData<T> {
6565
pub du: DetectUintData<T>,
6666
pub index: DetectUintIndex,
67+
// subslice
68+
pub start: i32,
69+
pub end: i32,
6770
}
6871

6972
fn parse_uint_index_precise(s: &str) -> IResult<&str, DetectUintIndex> {
@@ -85,8 +88,29 @@ fn parse_uint_index_val(s: &str) -> Option<DetectUintIndex> {
8588
Some(arg1)
8689
}
8790

91+
fn parse_uint_subslice_aux(s: &str) -> IResult<&str, (i32, i32)> {
92+
let (s, start) = nom_i32(s)?;
93+
let (s, _) = char(':')(s)?;
94+
let (s, end) = nom_i32(s)?;
95+
return Ok((s, (start, end)));
96+
}
97+
98+
fn parse_uint_subslice(parts: &[&str]) -> Option<(i32, i32)> {
99+
if parts.len() < 3 {
100+
return Some((0, 0));
101+
}
102+
let (_, (start, end)) = parse_uint_subslice_aux(parts[2]).ok()?;
103+
if start > 0 && end > 0 && end <= start {
104+
return None;
105+
}
106+
if start < 0 && end < 0 && end <= start {
107+
return None;
108+
}
109+
return Some((start, end));
110+
}
111+
88112
fn parse_uint_index(parts: &[&str]) -> Option<DetectUintIndex> {
89-
let index = if parts.len() == 2 {
113+
let index = if parts.len() >= 2 {
90114
match parts[1] {
91115
"all" => DetectUintIndex::All,
92116
"all1" => DetectUintIndex::All1,
@@ -103,36 +127,63 @@ fn parse_uint_index(parts: &[&str]) -> Option<DetectUintIndex> {
103127

104128
pub(crate) fn detect_parse_array_uint<T: DetectIntType>(s: &str) -> Option<DetectUintArrayData<T>> {
105129
let parts: Vec<&str> = s.split(',').collect();
106-
if parts.len() > 2 {
130+
if parts.len() > 3 {
107131
return None;
108132
}
109133

110134
let index = parse_uint_index(&parts)?;
111135
let (_, du) = detect_parse_uint::<T>(parts[0]).ok()?;
136+
let (start, end) = parse_uint_subslice(&parts)?;
112137

113-
Some(DetectUintArrayData { du, index })
138+
Some(DetectUintArrayData {
139+
du,
140+
index,
141+
start,
142+
end,
143+
})
114144
}
115145

116146
pub(crate) fn detect_parse_array_uint_enum<T1: DetectIntType, T2: EnumString<T1>>(
117147
s: &str,
118148
) -> Option<DetectUintArrayData<T1>> {
119149
let parts: Vec<&str> = s.split(',').collect();
120-
if parts.len() > 2 {
150+
if parts.len() > 3 {
121151
return None;
122152
}
123153

124154
let index = parse_uint_index(&parts)?;
125155
let du = detect_parse_uint_enum::<T1, T2>(parts[0])?;
156+
let (start, end) = parse_uint_subslice(&parts)?;
126157

127-
Some(DetectUintArrayData { du, index })
158+
Some(DetectUintArrayData {
159+
du,
160+
index,
161+
start,
162+
end,
163+
})
128164
}
129165

130166
pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
131167
array: &[T], ctx: &DetectUintArrayData<U>, get_value: impl Fn(&T) -> Option<U>, eof: bool,
132168
) -> c_int {
169+
let start = if ctx.start >= 0 {
170+
ctx.start as usize
171+
} else {
172+
((array.len() as i32) + ctx.start) as usize
173+
};
174+
let end = if ctx.end > 0 {
175+
ctx.end as usize
176+
} else {
177+
((array.len() as i32) + ctx.end) as usize
178+
};
179+
let subslice = if end > array.len() || start >= end {
180+
&array[..0]
181+
} else {
182+
&array[start..end]
183+
};
133184
match &ctx.index {
134185
DetectUintIndex::Any => {
135-
for response in array {
186+
for response in subslice {
136187
if let Some(code) = get_value(response) {
137188
if detect_match_uint::<U>(&ctx.du, code) {
138189
return 1;
@@ -143,7 +194,7 @@ pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
143194
}
144195
DetectUintIndex::OrAbsent => {
145196
let mut has_elem = false;
146-
for response in array {
197+
for response in subslice {
147198
if let Some(code) = get_value(response) {
148199
if detect_match_uint::<U>(&ctx.du, code) {
149200
return 1;
@@ -166,7 +217,7 @@ pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
166217
}
167218
}
168219
let mut nb = 0u32;
169-
for response in array {
220+
for response in subslice {
170221
if let Some(code) = get_value(response) {
171222
if detect_match_uint::<U>(&ctx.du, code) {
172223
nb += 1;
@@ -182,7 +233,7 @@ pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
182233
if !eof {
183234
return 0;
184235
}
185-
for response in array {
236+
for response in subslice {
186237
if let Some(code) = get_value(response) {
187238
if !detect_match_uint::<U>(&ctx.du, code) {
188239
return 0;
@@ -196,7 +247,7 @@ pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
196247
return 0;
197248
}
198249
let mut has_elem = false;
199-
for response in array {
250+
for response in subslice {
200251
if let Some(code) = get_value(response) {
201252
if !detect_match_uint::<U>(&ctx.du, code) {
202253
return 0;
@@ -212,17 +263,17 @@ pub(crate) fn detect_uint_match_at_index<T, U: DetectIntType>(
212263
DetectUintIndex::Index((oob, idx)) => {
213264
let index = if *idx < 0 {
214265
// negative values for backward indexing.
215-
((array.len() as i32) + idx) as usize
266+
((subslice.len() as i32) + idx) as usize
216267
} else {
217268
*idx as usize
218269
};
219-
if array.len() <= index {
270+
if subslice.len() <= index {
220271
if *oob && eof {
221272
return 1;
222273
}
223274
return 0;
224275
}
225-
if let Some(code) = get_value(&array[index]) {
276+
if let Some(code) = get_value(&subslice[index]) {
226277
return detect_match_uint::<U>(&ctx.du, code) as c_int;
227278
}
228279
return 0;

0 commit comments

Comments
 (0)