Skip to content

Commit f27ea82

Browse files
committed
detect: integer keywords now accept bitmasks
Ticket: 6648 Like &0x40=0x40 to test for a specific bit set
1 parent 08dc21e commit f27ea82

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

‎rust/src/detect/uint.rs‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ pub enum DetectUintMode {
3838
DetectUintModeRange,
3939
DetectUintModeNe,
4040
DetectUintModeNegRg,
41+
DetectUintModeBitmask,
42+
DetectUintModeNegBitmask,
4143
}
4244

4345
#[derive(Debug)]
@@ -173,6 +175,37 @@ pub fn detect_parse_uint_start_interval<T: DetectIntType>(
173175
))
174176
}
175177

178+
pub fn detect_parse_uint_bitmask<T: DetectIntType>(
179+
i: &str,
180+
) -> IResult<&str, DetectUintData<T>> {
181+
let (i, _) = opt(is_a(" "))(i)?;
182+
let (i, _) = tag("&")(i)?;
183+
let (i, _) = opt(is_a(" "))(i)?;
184+
let (i, arg1) = detect_parse_uint_value(i)?;
185+
let (i, _) = opt(is_a(" "))(i)?;
186+
let (i, neg) = opt(tag("!"))(i)?;
187+
let (i, _) = tag("=")(i)?;
188+
let (i, _) = opt(is_a(" "))(i)?;
189+
let (i, arg2) = detect_parse_uint_value(i)?;
190+
if arg2 & arg1 != arg2 {
191+
// could never match
192+
return Err(Err::Error(make_error(i, ErrorKind::Verify)));
193+
}
194+
let mode = if neg.is_none() {
195+
DetectUintMode::DetectUintModeBitmask
196+
} else {
197+
DetectUintMode::DetectUintModeNegBitmask
198+
};
199+
Ok((
200+
i,
201+
DetectUintData {
202+
arg1,
203+
arg2,
204+
mode,
205+
},
206+
))
207+
}
208+
176209
fn detect_parse_uint_start_interval_inclusive<T: DetectIntType>(
177210
i: &str,
178211
) -> IResult<&str, DetectUintData<T>> {
@@ -298,13 +331,24 @@ pub fn detect_match_uint<T: DetectIntType>(x: &DetectUintData<T>, val: T) -> boo
298331
return true;
299332
}
300333
}
334+
DetectUintMode::DetectUintModeBitmask => {
335+
if val & x.arg1 == x.arg2 {
336+
return true;
337+
}
338+
}
339+
DetectUintMode::DetectUintModeNegBitmask => {
340+
if val & x.arg1 != x.arg2 {
341+
return true;
342+
}
343+
}
301344
}
302345
return false;
303346
}
304347

305348
pub fn detect_parse_uint_notending<T: DetectIntType>(i: &str) -> IResult<&str, DetectUintData<T>> {
306349
let (i, _) = opt(is_a(" "))(i)?;
307350
let (i, uint) = alt((
351+
detect_parse_uint_bitmask,
308352
detect_parse_uint_start_interval,
309353
detect_parse_uint_start_equal,
310354
detect_parse_uint_start_symbol,
@@ -487,6 +531,24 @@ mod tests {
487531
assert_eq!(ctx.mode, DetectUintMode::DetectUintModeGt);
488532
}
489533

534+
#[test]
535+
fn test_parse_uint_bitmask() {
536+
let (_, val) = detect_parse_uint::<u64>("&0x40!=0").unwrap();
537+
assert_eq!(val.arg1, 0x40);
538+
assert_eq!(val.arg2, 0);
539+
assert_eq!(val.mode, DetectUintMode::DetectUintModeNegBitmask);
540+
assert!(!detect_match_uint(&val, 0xBF));
541+
assert!(detect_match_uint(&val, 0x40));
542+
let (_, val) = detect_parse_uint::<u64>("&0xc0=0x80").unwrap();
543+
assert_eq!(val.arg1, 0xc0);
544+
assert_eq!(val.arg2, 0x80);
545+
assert_eq!(val.mode, DetectUintMode::DetectUintModeBitmask);
546+
assert!(detect_match_uint(&val, 0x80));
547+
assert!(!detect_match_uint(&val, 0x40));
548+
assert!(!detect_match_uint(&val, 0xc0));
549+
// could never match
550+
assert!(detect_parse_uint::<u64>("&0xc0=12").is_err());
551+
}
490552
#[test]
491553
fn test_parse_uint_hex() {
492554
let (_, val) = detect_parse_uint::<u64>("0x100").unwrap();

0 commit comments

Comments
 (0)