use crate::detect::error::RuleParseError;
use crate::detect::parser::{parse_var, take_until_whitespace, ResultValue};
+use crate::detect::{get_endian_value, get_string_value, ByteBase, ByteEndian};
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
RightShift = 7,
}
-#[repr(u8)]
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-// endian <big|little|dce>
-pub enum ByteMathEndian {
- _EndianNone = 0,
- BigEndian = 1,
- LittleEndian = 2,
- EndianDCE = 3,
-}
-pub const DETECT_BYTEMATH_ENDIAN_DEFAULT: ByteMathEndian = ByteMathEndian::BigEndian;
+pub const DETECT_BYTEMATH_ENDIAN_DEFAULT: ByteEndian = ByteEndian::BigEndian;
-#[repr(u8)]
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum ByteMathBase {
- _BaseNone = 0,
- BaseOct = 8,
- BaseDec = 10,
- BaseHex = 16,
-}
-const BASE_DEFAULT: ByteMathBase = ByteMathBase::BaseDec;
+const BASE_DEFAULT: ByteBase = ByteBase::BaseDec;
// Fixed position parameter count: bytes, offset, oper, rvalue, result
// result is not parsed with the fixed position parameters as it's
local_id: u8,
nbytes: u8,
oper: ByteMathOperator,
- endian: ByteMathEndian, // big, little, dce
- base: ByteMathBase, // From string or dce
+ endian: ByteEndian, // big, little, dce
+ base: ByteBase, // From string or dce
}
impl Drop for DetectByteMathData {
}
}
-fn get_string_value(value: &str) -> Result<ByteMathBase, ()> {
- let res = match value {
- "hex" => ByteMathBase::BaseHex,
- "oct" => ByteMathBase::BaseOct,
- "dec" => ByteMathBase::BaseDec,
- _ => return Err(()),
- };
-
- Ok(res)
-}
-
fn get_oper_value(value: &str) -> Result<ByteMathOperator, ()> {
let res = match value {
"+" => ByteMathOperator::Addition,
Ok(res)
}
-fn get_endian_value(value: &str) -> Result<ByteMathEndian, ()> {
- let res = match value {
- "big" => ByteMathEndian::BigEndian,
- "little" => ByteMathEndian::LittleEndian,
- "dce" => ByteMathEndian::EndianDCE,
- _ => return Err(()),
- };
-
- Ok(res)
-}
-
fn parse_bytemath(input: &str) -> IResult<&str, DetectByteMathData, RuleParseError<&str>> {
// Inner utility function for easy error creation.
fn make_error(reason: String) -> nom7::Err<RuleParseError<&'static str>> {
return Err(make_error("endianess already set".to_string()));
}
byte_math.flags |= DETECT_BYTEMATH_FLAG_ENDIAN;
- byte_math.endian = ByteMathEndian::EndianDCE;
+ byte_math.endian = ByteEndian::EndianDCE;
}
"string" => {
if 0 != (byte_math.flags & DETECT_BYTEMATH_FLAG_STRING) {
}
fn valid_test(
- args: &str, nbytes: u8, offset: i32, oper: ByteMathOperator, rvalue_str: &str, nbytes_str: &str, rvalue: u32,
- result: &str, base: ByteMathBase, endian: ByteMathEndian, bitmask_val: u32, flags: u8,
+ args: &str, nbytes: u8, offset: i32, oper: ByteMathOperator, rvalue_str: &str,
+ nbytes_str: &str, rvalue: u32, result: &str, base: ByteBase, endian: ByteEndian,
+ bitmask_val: u32, flags: u8,
) {
let bmd = DetectByteMathData {
nbytes,
"",
0,
"myresult",
- ByteMathBase::BaseDec,
- ByteMathEndian::EndianDCE,
+ ByteBase::BaseDec,
+ ByteEndian::EndianDCE,
0,
DETECT_BYTEMATH_FLAG_RVALUE_VAR
| DETECT_BYTEMATH_FLAG_STRING
"",
99,
"other",
- ByteMathBase::BaseDec,
- ByteMathEndian::EndianDCE,
+ ByteBase::BaseDec,
+ ByteEndian::EndianDCE,
0,
DETECT_BYTEMATH_FLAG_STRING | DETECT_BYTEMATH_FLAG_ENDIAN,
);
0,
"foo",
BASE_DEFAULT,
- ByteMathEndian::BigEndian,
+ ByteEndian::BigEndian,
0,
DETECT_BYTEMATH_FLAG_RVALUE_VAR,
);
0,
"foo",
BASE_DEFAULT,
- ByteMathEndian::BigEndian,
+ ByteEndian::BigEndian,
0,
DETECT_BYTEMATH_FLAG_RVALUE_VAR | DETECT_BYTEMATH_FLAG_NBYTES_VAR,
);
"",
99,
"other",
- ByteMathBase::BaseDec,
- ByteMathEndian::BigEndian,
+ ByteBase::BaseDec,
+ ByteEndian::BigEndian,
0,
DETECT_BYTEMATH_FLAG_STRING | DETECT_BYTEMATH_FLAG_ENDIAN,
);
rvalue: 0,
result: CString::new("foo").unwrap().into_raw(),
endian: DETECT_BYTEMATH_ENDIAN_DEFAULT,
- base: ByteMathBase::BaseDec,
+ base: ByteBase::BaseDec,
flags: DETECT_BYTEMATH_FLAG_RVALUE_VAR | DETECT_BYTEMATH_FLAG_STRING,
..Default::default()
};
- let (_, val) = parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, string dec",
- ).unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, string dec")
+ .unwrap();
assert_eq!(val, bmd);
bmd.flags = DETECT_BYTEMATH_FLAG_RVALUE_VAR;
bmd.base = BASE_DEFAULT;
- let (_, val) = parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo").unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo").unwrap();
assert_eq!(val, bmd);
bmd.flags = DETECT_BYTEMATH_FLAG_RVALUE_VAR | DETECT_BYTEMATH_FLAG_STRING;
- bmd.base = ByteMathBase::BaseHex;
- let (_, val) = parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, string hex").unwrap();
+ bmd.base = ByteBase::BaseHex;
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, string hex")
+ .unwrap();
assert_eq!(val, bmd);
- bmd.base = ByteMathBase::BaseOct;
- let (_, val) = parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, string oct",
- ).unwrap();
+ bmd.base = ByteBase::BaseOct;
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, string oct")
+ .unwrap();
assert_eq!(val, bmd);
}
#[test]
fn test_parser_string_invalid() {
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, string decimal"
- )
- .is_err()
- );
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, string hexadecimal"
- )
- .is_err()
- );
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, string octal"
- )
- .is_err()
- );
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, string decimal"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, string hexadecimal"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, string octal"
+ )
+ .is_err());
}
#[test]
#[test]
fn test_parser_bitmask_invalid() {
- assert!(
- parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask 0x")
- .is_err()
- );
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask x12345678"
- )
- .is_err()
- );
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask X12345678"
- )
- .is_err()
- );
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask 0x123456789012"
- )
- .is_err()
- );
- assert!(
- parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask 0q")
- .is_err()
- );
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask maple"
- )
- .is_err()
- );
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask 0xGHIJKLMN"
- )
- .is_err()
- );
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask #*#*@-"
- )
- .is_err()
- );
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask 0x"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask x12345678"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask X12345678"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask 0x123456789012"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask 0q"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask maple"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask 0xGHIJKLMN"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask #*#*@-"
+ )
+ .is_err());
}
#[test]
rvalue_str: CString::new("myrvalue").unwrap().into_raw(),
rvalue: 0,
result: CString::new("foo").unwrap().into_raw(),
- endian: ByteMathEndian::BigEndian,
+ endian: ByteEndian::BigEndian,
base: BASE_DEFAULT,
flags: DETECT_BYTEMATH_FLAG_RVALUE_VAR | DETECT_BYTEMATH_FLAG_BITMASK,
..Default::default()
bmd.bitmask_val = 0x12345678;
let (_, val) = parse_bytemath(
"bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask 0x12345678",
- ).unwrap();
+ )
+ .unwrap();
assert_eq!(val, bmd);
-
bmd.bitmask_val = 0xffff1234;
let (_, val) = parse_bytemath(
"bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask ffff1234",
- ).unwrap();
+ )
+ .unwrap();
assert_eq!(val, bmd);
-
bmd.bitmask_val = 0xffff1234;
let (_, val) = parse_bytemath(
"bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, bitmask 0Xffff1234",
- ).unwrap();
+ )
+ .unwrap();
assert_eq!(val, bmd);
-
}
#[test]
fn test_parser_endian_valid() {
rvalue_str: CString::new("myrvalue").unwrap().into_raw(),
rvalue: 0,
result: CString::new("foo").unwrap().into_raw(),
- endian: ByteMathEndian::BigEndian,
+ endian: ByteEndian::BigEndian,
base: BASE_DEFAULT,
flags: DETECT_BYTEMATH_FLAG_RVALUE_VAR | DETECT_BYTEMATH_FLAG_ENDIAN,
..Default::default()
};
- let (_, val) = parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, endian big",
- ).unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, endian big")
+ .unwrap();
assert_eq!(val, bmd);
-
- bmd.endian = ByteMathEndian::LittleEndian;
+ bmd.endian = ByteEndian::LittleEndian;
let (_, val) = parse_bytemath(
"bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, endian little",
- ).unwrap();
+ )
+ .unwrap();
assert_eq!(val, bmd);
-
- bmd.endian = ByteMathEndian::EndianDCE;
- let (_, val) = parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, dce").unwrap();
+ bmd.endian = ByteEndian::EndianDCE;
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, dce")
+ .unwrap();
assert_eq!(val, bmd);
-
bmd.endian = DETECT_BYTEMATH_ENDIAN_DEFAULT;
bmd.flags = DETECT_BYTEMATH_FLAG_RVALUE_VAR;
- let (_, val) = parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo").unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo").unwrap();
assert_eq!(val, bmd);
-
}
#[test]
fn test_parser_endian_invalid() {
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, endian bigger"
- )
- .is_err()
- );
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, endian smaller"
- )
- .is_err()
- );
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, endian bigger"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, endian smaller"
+ )
+ .is_err());
// endianess can only be specified once
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, endian big, dce"
- )
- .is_err()
- );
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, endian small, endian big"
- )
- .is_err()
- );
- assert!(
- parse_bytemath(
- "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, endian small, dce"
- )
- .is_err()
- );
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, endian big, dce"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, endian small, endian big"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 3933, oper +, rvalue myrvalue, result foo, endian small, dce"
+ )
+ .is_err());
}
#[test]
rvalue_str: CString::new("myrvalue").unwrap().into_raw(),
rvalue: 0,
result: CString::new("foo").unwrap().into_raw(),
- endian: ByteMathEndian::BigEndian,
+ endian: ByteEndian::BigEndian,
base: BASE_DEFAULT,
flags: DETECT_BYTEMATH_FLAG_RVALUE_VAR,
..Default::default()
};
- let (_, val) = parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo").unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, result foo").unwrap();
assert_eq!(val, bmd);
-
bmd.oper = ByteMathOperator::Subtraction;
- let (_, val) = parse_bytemath("bytes 4, offset 3933, oper -, rvalue myrvalue, result foo").unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 3933, oper -, rvalue myrvalue, result foo").unwrap();
assert_eq!(val, bmd);
-
bmd.oper = ByteMathOperator::Multiplication;
- let (_, val) = parse_bytemath("bytes 4, offset 3933, oper *, rvalue myrvalue, result foo").unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 3933, oper *, rvalue myrvalue, result foo").unwrap();
assert_eq!(val, bmd);
bmd.oper = ByteMathOperator::Division;
- let (_, val) = parse_bytemath("bytes 4, offset 3933, oper /, rvalue myrvalue, result foo").unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 3933, oper /, rvalue myrvalue, result foo").unwrap();
assert_eq!(val, bmd);
bmd.oper = ByteMathOperator::RightShift;
- let (_, val) = parse_bytemath("bytes 4, offset 3933, oper >>, rvalue myrvalue, result foo").unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 3933, oper >>, rvalue myrvalue, result foo").unwrap();
assert_eq!(val, bmd);
bmd.oper = ByteMathOperator::LeftShift;
- let (_, val) = parse_bytemath("bytes 4, offset 3933, oper <<, rvalue myrvalue, result foo").unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 3933, oper <<, rvalue myrvalue, result foo").unwrap();
assert_eq!(val, bmd);
-
}
#[test]
fn test_parser_oper_invalid() {
- assert!(
- parse_bytemath("bytes 4, offset 0, oper !, rvalue myvalue, result foo").is_err()
- );
- assert!(
- parse_bytemath("bytes 4, offset 0, oper ^, rvalue myvalue, result foo").is_err()
- );
- assert!(
- parse_bytemath("bytes 4, offset 0, oper <>, rvalue myvalue, result foo").is_err()
- );
- assert!(
- parse_bytemath("bytes 4, offset 0, oper ><, rvalue myvalue, result foo").is_err()
- );
- assert!(
- parse_bytemath("bytes 4, offset 0, oper <, rvalue myvalue, result foo").is_err()
- );
- assert!(
- parse_bytemath("bytes 4, offset 0, oper >, rvalue myvalue, result foo").is_err()
- );
+ assert!(parse_bytemath("bytes 4, offset 0, oper !, rvalue myvalue, result foo").is_err());
+ assert!(parse_bytemath("bytes 4, offset 0, oper ^, rvalue myvalue, result foo").is_err());
+ assert!(parse_bytemath("bytes 4, offset 0, oper <>, rvalue myvalue, result foo").is_err());
+ assert!(parse_bytemath("bytes 4, offset 0, oper ><, rvalue myvalue, result foo").is_err());
+ assert!(parse_bytemath("bytes 4, offset 0, oper <, rvalue myvalue, result foo").is_err());
+ assert!(parse_bytemath("bytes 4, offset 0, oper >, rvalue myvalue, result foo").is_err());
}
#[test]
..Default::default()
};
- let (_, val) = parse_bytemath("bytes 4, offset 47303, oper *, rvalue 4294967295 , result foo").unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 47303, oper *, rvalue 4294967295 , result foo")
+ .unwrap();
assert_eq!(val, bmd);
-
bmd.rvalue = 1;
- let (_, val) = parse_bytemath("bytes 4, offset 47303, oper *, rvalue 1, result foo").unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 47303, oper *, rvalue 1, result foo").unwrap();
assert_eq!(val, bmd);
bmd.rvalue = 0;
- let (_, val) = parse_bytemath("bytes 4, offset 47303, oper *, rvalue 0, result foo").unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 47303, oper *, rvalue 0, result foo").unwrap();
assert_eq!(val, bmd);
-
}
#[test]
..Default::default()
};
- let (_, val) = parse_bytemath("bytes 4, offset -65535, oper *, rvalue myrvalue, result foo").unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset -65535, oper *, rvalue myrvalue, result foo").unwrap();
assert_eq!(val, bmd);
-
bmd.offset = 65535;
- let (_, val) = parse_bytemath("bytes 4, offset 65535, oper *, rvalue myrvalue, result foo").unwrap();
+ let (_, val) =
+ parse_bytemath("bytes 4, offset 65535, oper *, rvalue myrvalue, result foo").unwrap();
assert_eq!(val, bmd);
-
}
#[test]
parse_bytemath("bytes 4, offset 3933, endian big, rvalue myrvalue, result foo")
.is_err()
);
- assert!(
- parse_bytemath("bytes 4, offset 3933, oper +, endian big, result foo").is_err()
- );
+ assert!(parse_bytemath("bytes 4, offset 3933, oper +, endian big, result foo").is_err());
assert!(
parse_bytemath("bytes 4, offset 3933, oper +, rvalue myrvalue, endian big").is_err()
);
assert!(parse_bytemath("bytes nan").is_err());
assert!(parse_bytemath("bytes 4, offset nan").is_err());
assert!(parse_bytemath("bytes 4, offset 0, three 3, four 4, five 5, six 6, seven 7, eight 8, nine 9, ten 10, eleven 11").is_err());
- assert!(
- parse_bytemath("bytes 4, offset 0, oper ><, rvalue myrvalue").is_err()
- );
+ assert!(parse_bytemath("bytes 4, offset 0, oper ><, rvalue myrvalue").is_err());
assert!(
parse_bytemath("bytes 4, offset 0, oper +, rvalue myrvalue, endian endian").is_err()
);
}
#[test]
fn test_parser_multiple() {
- assert!(
- parse_bytemath(
- "bytes 4, bytes 4, offset 0, oper +, rvalue myrvalue, result myresult, endian big"
- )
- .is_err()
- );
- assert!(
- parse_bytemath(
- "bytes 4, offset 0, offset 0, oper +, rvalue myrvalue, result myresult, endian big"
- )
- .is_err()
- );
- assert!(
- parse_bytemath(
- "bytes 4, offset 0, oper +, oper +, rvalue myrvalue, result myresult, endian big"
- )
- .is_err()
- );
+ assert!(parse_bytemath(
+ "bytes 4, bytes 4, offset 0, oper +, rvalue myrvalue, result myresult, endian big"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 0, offset 0, oper +, rvalue myrvalue, result myresult, endian big"
+ )
+ .is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 0, oper +, oper +, rvalue myrvalue, result myresult, endian big"
+ )
+ .is_err());
assert!(parse_bytemath("bytes 4, offset 0, oper +, rvalue myrvalue, rvalue myrvalue, result myresult, endian big").is_err());
assert!(parse_bytemath("bytes 4, offset 0, oper +, rvalue myrvalue, result myresult, result myresult, endian big").is_err());
- assert!(parse_bytemath("bytes 4, offset 0, oper +, rvalue myrvalue, result myresult, endian big, endian big").is_err());
+ assert!(parse_bytemath(
+ "bytes 4, offset 0, oper +, rvalue myrvalue, result myresult, endian big, endian big"
+ )
+ .is_err());
}
}