rust/detect: convert remaining detection rule parsers to nom 8

Ticket: #8051
pull/14332/head
Jason Ish 9 months ago committed by Victor Julien
parent dea3f9e260
commit 25c98af0e8

@ -15,14 +15,13 @@
* 02110-1301, USA.
*/
use nom7::{
use nom8::{
branch::alt,
bytes::complete::{is_a, tag, tag_no_case, take_while},
character::complete::{char, digit1},
combinator::{all_consuming, map, map_opt, opt, recognize, value, verify},
error::{make_error, ErrorKind},
sequence::tuple,
Err, IResult,
Err, IResult, Parser,
};
use num::traits::float::FloatCore;
@ -94,25 +93,25 @@ pub fn parse_float_value<T: DetectFloatType>(input: &str) -> IResult<&str, T> {
}),
// Handle numeric parsing, including scientific notation
map_opt(
recognize(tuple((
recognize((
opt(alt((tag("+"), tag("-")))), // Handle optional signs
alt((digit1, recognize(tuple((tag("."), digit1))))), // Handle integers & `.5`
opt(tuple((tag("."), digit1))), // Handle decimals like `5.`
opt(tuple((
alt((digit1, recognize((tag("."), digit1)))), // Handle integers & `.5`
opt((tag("."), digit1)), // Handle decimals like `5.`
opt((
tag_no_case("e"),
opt(alt((tag("+"), tag("-")))),
digit1,
))), // Handle `1e10`, `-1e-5`
))),
)), // Handle `1e10`, `-1e-5`
)),
|float_str: &str| <T as DetectFloatType>::from_str(float_str),
),
))(input)
)).parse(input)
}
fn detect_parse_float_start_equal<T: DetectFloatType>(
i: &str,
) -> IResult<&str, DetectFloatData<T>> {
let (i, _) = opt(tag("="))(i)?;
let (i, _) = opt(is_a(" "))(i)?;
let (i, _) = opt(tag("=")).parse(i)?;
let (i, _) = opt(is_a(" ")).parse(i)?;
let (i, arg1) = parse_float_value::<T>(i)?;
Ok((
i,
@ -127,14 +126,14 @@ fn detect_parse_float_start_equal<T: DetectFloatType>(
pub fn detect_parse_float_start_interval<T: DetectFloatType>(
i: &str,
) -> IResult<&str, DetectFloatData<T>> {
let (i, neg) = opt(char('!'))(i)?;
let (i, neg) = opt(char('!')).parse(i)?;
let (i, arg1) = parse_float_value::<T>(i)?;
let (i, _) = opt(is_a(" "))(i)?;
let (i, _) = alt((tag("-"), tag("<>")))(i)?;
let (i, _) = opt(is_a(" "))(i)?;
let (i, _) = opt(is_a(" ")).parse(i)?;
let (i, _) = alt((tag("-"), tag("<>"))).parse(i)?;
let (i, _) = opt(is_a(" ")).parse(i)?;
let (i, arg2) = verify(parse_float_value::<T>, |x| {
*x > arg1 && *x - arg1 > <T as FloatCore>::epsilon()
})(i)?;
}).parse(i)?;
let mode = if neg.is_some() {
DetectFloatMode::DetectFloatModeNegRg
} else {
@ -151,7 +150,7 @@ fn detect_parse_float_mode(i: &str) -> IResult<&str, DetectFloatMode> {
value(DetectFloatMode::DetectFloatModeLt, tag("<")),
value(DetectFloatMode::DetectFloatModeNe, tag("!=")),
value(DetectFloatMode::DetectFloatModeEqual, tag("=")),
))(i)?;
)).parse(i)?;
Ok((i, mode))
}
@ -159,7 +158,7 @@ fn detect_parse_float_start_symbol<T: DetectFloatType>(
i: &str,
) -> IResult<&str, DetectFloatData<T>> {
let (i, mode) = detect_parse_float_mode(i)?;
let (i, _) = opt(is_a(" "))(i)?;
let (i, _) = opt(is_a(" ")).parse(i)?;
let (i, arg1) = parse_float_value::<T>(i)?;
match mode {
@ -214,17 +213,17 @@ pub fn detect_match_float<T: DetectFloatType>(x: &DetectFloatData<T>, val: T) ->
pub fn detect_parse_float<T: DetectFloatType>(i: &str) -> IResult<&str, DetectFloatData<T>> {
let (i, float) = detect_parse_float_notending(i)?;
let (i, _) = all_consuming(take_while(|c| c == ' '))(i)?;
let (i, _) = all_consuming(take_while(|c| c == ' ')).parse(i)?;
Ok((i, float))
}
fn detect_parse_float_notending<T: DetectFloatType>(i: &str) -> IResult<&str, DetectFloatData<T>> {
let (i, _) = opt(is_a(" "))(i)?;
let (i, _) = opt(is_a(" ")).parse(i)?;
let (i, float) = alt((
detect_parse_float_start_interval,
detect_parse_float_start_equal,
detect_parse_float_start_symbol,
))(i)?;
)).parse(i)?;
Ok((i, float))
}

@ -22,17 +22,16 @@ use std::{cmp::Ordering, ffi::CStr};
// Rust 1.64.0.
use std::os::raw::{c_char, c_int};
use nom7::bytes::complete::take_while;
use nom7::combinator::map;
use nom7::multi::{many1, separated_list1};
use nom7::sequence::tuple;
use nom7::{
use nom8::bytes::complete::take_while;
use nom8::combinator::map;
use nom8::multi::{many1, separated_list1};
use nom8::{
branch::alt,
bytes::complete::{tag, take_till},
character::complete::{char, multispace0},
combinator::map_res,
sequence::preceded,
IResult,
IResult, Parser,
};
#[derive(Debug, Eq, PartialEq)]
@ -146,8 +145,8 @@ impl SuricataVersion {
/// ]
fn parse_version_expression(input: &str) -> IResult<&str, Vec<Vec<RuleRequireVersion>>> {
let sep = preceded(multispace0, tag("|"));
let inner_parser = many1(tuple((parse_op, parse_version)));
let (input, versions) = separated_list1(sep, inner_parser)(input)?;
let inner_parser = many1((parse_op, parse_version));
let (input, versions) = separated_list1(sep, inner_parser).parse(input)?;
let versions = versions
.into_iter()
@ -195,7 +194,7 @@ fn parse_op(input: &str) -> IResult<&str, VersionCompareOp> {
map(tag("<="), |_| VersionCompareOp::Lte),
map(tag("<"), |_| VersionCompareOp::Lt),
)),
)(input)
).parse(input)
}
/// Parse the next part of the version.
@ -205,21 +204,21 @@ fn parse_next_version_part(input: &str) -> IResult<&str, u8> {
map_res(
take_till(|c| c == '.' || c == '-' || c == ' '),
|s: &str| s.parse::<u8>(),
)(input)
).parse(input)
}
/// Parse a version string into a SuricataVersion.
fn parse_version(input: &str) -> IResult<&str, SuricataVersion> {
let (input, major) = preceded(multispace0, parse_next_version_part)(input)?;
let (input, major) = preceded(multispace0, parse_next_version_part).parse(input)?;
let (input, minor) = if input.is_empty() || input.starts_with(' ') {
(input, 0)
} else {
preceded(char('.'), parse_next_version_part)(input)?
preceded(char('.'), parse_next_version_part).parse(input)?
};
let (input, patch) = if input.is_empty() || input.starts_with(' ') {
(input, 0)
} else {
preceded(char('.'), parse_next_version_part)(input)?
preceded(char('.'), parse_next_version_part).parse(input)?
};
Ok((input, SuricataVersion::new(major, minor, patch)))
@ -230,8 +229,8 @@ fn parse_key_value(input: &str) -> IResult<&str, (&str, &str)> {
let (input, key) = preceded(
multispace0,
take_while(|c: char| c.is_alphanumeric() || c == '-' || c == '_'),
)(input)?;
let (input, value) = preceded(multispace0, take_till(|c: char| c == ','))(input)?;
).parse(input)?;
let (input, value) = preceded(multispace0, take_till(|c: char| c == ',')).parse(input)?;
Ok((input, (key, value)))
}

@ -20,8 +20,9 @@ use crate::detect::uint::{
DetectUintMode,
};
use crate::detect::EnumString;
use nom7::bytes::complete::take;
use nom7::error::Error;
use nom8::bytes::complete::take;
use nom8::error::Error;
use nom8::Parser;
use std::ffi::CStr;
@ -52,7 +53,7 @@ pub fn tcp_flags_parse(s: &str) -> Option<DetectUintData<u8>> {
let mut arg2 = 0xffu8;
let mut s2 = s;
while !s2.is_empty() {
let (s, vals) = take::<usize, &str, Error<_>>(1usize)(s2).ok()?;
let (s, vals) = take::<usize, &str, Error<_>>(1usize).parse(s2).ok()?;
s2 = s;
let vals = match vals {
"1" => "C",

@ -15,10 +15,11 @@
* 02110-1301, USA.
*/
use nom7::character::complete::{char, digit1, space0};
use nom7::combinator::{map_opt, opt, verify};
use nom7::error::{make_error, ErrorKind};
use nom7::IResult;
use nom8::character::complete::{char, digit1, space0};
use nom8::combinator::{map_opt, opt, verify};
use nom8::error::{make_error, ErrorKind};
use nom8::Parser;
use nom8::IResult;
use std::os::raw::{c_int, c_void};
@ -80,35 +81,35 @@ pub struct DetectCipServiceData {
}
fn enip_parse_cip_service(i: &str) -> IResult<&str, DetectCipServiceData> {
let (i, _) = space0(i)?;
let (i, _) = space0.parse(i)?;
let (i, service) = verify(map_opt(digit1, |s: &str| s.parse::<u8>().ok()), |&v| {
v < 0x80
})(i)?;
}).parse(i)?;
let mut class = None;
let mut attribute = None;
let (i, _) = space0(i)?;
let (i, comma) = opt(char(','))(i)?;
let (i, _) = space0.parse(i)?;
let (i, comma) = opt(char(',')).parse(i)?;
let mut input = i;
if comma.is_some() {
let (i, _) = space0(i)?;
let (i, class1) = map_opt(digit1, |s: &str| s.parse::<u32>().ok())(i)?;
let (i, _) = space0.parse(i)?;
let (i, class1) = map_opt(digit1, |s: &str| s.parse::<u32>().ok()).parse(i)?;
class = Some(class1);
let (i, _) = space0(i)?;
let (i, comma) = opt(char(','))(i)?;
let (i, _) = space0.parse(i)?;
let (i, comma) = opt(char(',')).parse(i)?;
input = i;
if comma.is_some() {
let (i, _) = space0(i)?;
let (i, negation) = opt(char('!'))(i)?;
let (i, attr1) = map_opt(digit1, |s: &str| s.parse::<u32>().ok())(i)?;
let (i, _) = space0.parse(i)?;
let (i, negation) = opt(char('!')).parse(i)?;
let (i, attr1) = map_opt(digit1, |s: &str| s.parse::<u32>().ok()).parse(i)?;
if negation.is_none() {
attribute = Some(attr1);
}
input = i;
}
}
let (i, _) = space0(input)?;
let (i, _) = space0.parse(input)?;
if !i.is_empty() {
return Err(nom7::Err::Error(make_error(i, ErrorKind::NonEmpty)));
return Err(nom8::Err::Error(make_error(i, ErrorKind::NonEmpty)));
}
return Ok((
i,

@ -32,12 +32,13 @@ use crate::detect::uint::{
use crate::detect::{SIGMATCH_INFO_ENUM_UINT, SIGMATCH_INFO_MULTI_UINT};
use kerberos_parser::krb5::EncryptionType;
use nom7::branch::alt;
use nom7::bytes::complete::{is_a, tag, take_while, take_while1};
use nom7::character::complete::char;
use nom7::combinator::{all_consuming, map_res, opt};
use nom7::multi::many1;
use nom7::IResult;
use nom8::branch::alt;
use nom8::bytes::complete::{is_a, tag, take_while, take_while1};
use nom8::character::complete::char;
use nom8::combinator::{all_consuming, map_res, opt};
use nom8::multi::many1;
use nom8::IResult;
use nom8::Parser;
use std::ffi::{c_int, CStr};
use std::os::raw::c_void;
@ -124,8 +125,8 @@ pub enum DetectKrb5TicketEncryptionData {
}
pub fn detect_parse_encryption_weak(i: &str) -> IResult<&str, DetectKrb5TicketEncryptionData> {
let (i, neg) = opt(char('!'))(i)?;
let (i, _) = tag("weak")(i)?;
let (i, neg) = opt(char('!')).parse(i)?;
let (i, _) = tag("weak").parse(i)?;
let value = neg.is_none();
return Ok((i, DetectKrb5TicketEncryptionData::WEAK(value)));
}
@ -189,18 +190,18 @@ pub fn is_alphanumeric_or_dash(chr: char) -> bool {
}
pub fn detect_parse_encryption_item(i: &str) -> IResult<&str, EncryptionType> {
let (i, _) = opt(is_a(" "))(i)?;
let (i, _) = opt(is_a(" ")).parse(i)?;
let (i, e) = map_res(take_while1(is_alphanumeric_or_dash), |s: &str| {
EncryptionType::from_str(s)
})(i)?;
let (i, _) = opt(is_a(" "))(i)?;
let (i, _) = opt(char(','))(i)?;
}).parse(i)?;
let (i, _) = opt(is_a(" ")).parse(i)?;
let (i, _) = opt(char(',')).parse(i)?;
return Ok((i, e));
}
pub fn detect_parse_encryption_list(i: &str) -> IResult<&str, DetectKrb5TicketEncryptionData> {
let mut l = DetectKrb5TicketEncryptionList::new();
let (i, v) = many1(detect_parse_encryption_item)(i)?;
let (i, v) = many1(detect_parse_encryption_item).parse(i)?;
for &val in v.iter() {
let vali = val.0;
// KRB_TICKET_FASTARRAY_SIZE is a constant typed usize but which fits in a i32
@ -216,9 +217,9 @@ pub fn detect_parse_encryption_list(i: &str) -> IResult<&str, DetectKrb5TicketEn
}
pub fn detect_parse_encryption(i: &str) -> IResult<&str, DetectKrb5TicketEncryptionData> {
let (i, _) = opt(is_a(" "))(i)?;
let (i, parsed) = alt((detect_parse_encryption_weak, detect_parse_encryption_list))(i)?;
let (i, _) = all_consuming(take_while(|c| c == ' '))(i)?;
let (i, _) = opt(is_a(" ")).parse(i)?;
let (i, parsed) = alt((detect_parse_encryption_weak, detect_parse_encryption_list)).parse(i)?;
let (i, _) = all_consuming(take_while(|c| c == ' ')).parse(i)?;
return Ok((i, parsed));
}

Loading…
Cancel
Save