diff --git a/Cargo.toml b/Cargo.toml index a76c51d..637d7d9 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ itertools = "0.10.3" pdb = "0.8.0" petgraph = "0.6.2" regex = "1.5" +fancy-regex = { git = "https://github.com/mnaza/fancy-regex.git" } serde = { version = "1", features = ["derive"] } smda = { git = "https://github.com/marirs/smda-rs.git" } thiserror = "1" diff --git a/src/error.rs b/src/error.rs index 14df2ca..cd672cd 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,6 +5,8 @@ pub enum Error { #[error("{0}")] RegexError(#[from] regex::Error), #[error("{0}")] + FancyRegexError(#[from] fancy_regex::Error), + #[error("{0}")] FromHexError(#[from] hex::FromHexError), #[error("{0}")] YamlError(#[from] yaml_rust::ScanError), @@ -43,6 +45,8 @@ pub enum Error { InvalidScope(u32, String), #[error("invalid static scope: {0}")] InvalidStaticScope(u32), + #[error("{0}")] + UndefinedComType(String), #[error("invalid dynamic scope: {0}")] InvalidDynamicScope(u32), #[error("{0}")] diff --git a/src/rules/features.rs b/src/rules/features.rs index 1acb143..33083a5 100755 --- a/src/rules/features.rs +++ b/src/rules/features.rs @@ -7,6 +7,24 @@ use crate::{rules::Value, Error, Result}; use super::{Scope, Scopes}; +#[derive(Debug, Clone, PartialEq, Hash, Eq)] +pub enum ComType { + Class, + Interface, +} + +impl TryInto for &str { + type Error = Error; + + fn try_into(self) -> std::result::Result { + match self { + "class" => Ok(ComType::Class), + "interface" => Ok(ComType::Interface), + _ => Err(Error::UndefinedComType(self.to_string())), + } + } +} + #[derive(Debug, Clone, PartialEq, Hash, Eq)] pub enum FeatureAccess { Read, @@ -40,6 +58,7 @@ pub enum RuleFeatureType { Class, OperandNumber(usize), OperandOffset(usize), + ComType(ComType), } pub trait FeatureT { @@ -198,6 +217,10 @@ impl Feature { RuleFeatureType::OperandOffset(a) => Ok(Feature::OperandOffset( OperandOffsetFeature::new(&a, &value.get_int()? as &i128, description)?, )), + RuleFeatureType::ComType(_ct) => { + //TODO + unimplemented!() + } } } @@ -1135,7 +1158,7 @@ impl SubstringFeature { pub struct RegexFeature { value: String, _description: String, - re: regex::bytes::Regex, + re: fancy_regex::Regex, scopes: HashSet, } @@ -1145,15 +1168,15 @@ impl RegexFeature { if value.ends_with("/i") { rre = r"(?-u)(?s)(?i)".to_string() + &value["/".len()..value.len() - "/i".len()]; } - rre = rre.replace("\\/", "/"); - rre = rre.replace("\\\"", "\""); - rre = rre.replace("\\'", "'"); - rre = rre.replace("\\%", "%"); - let rr = match regex::bytes::Regex::new(&rre) { + // rre = rre.replace("\\/", "/"); + // rre = rre.replace("\\\"", "\""); + // rre = rre.replace("\\'", "'"); + // rre = rre.replace("\\%", "%"); + let rr = match fancy_regex::Regex::new(&rre) { Ok(s) => s, Err(e) => { println!("{:?}", e); - return Err(Error::RegexError(e)); + return Err(Error::FancyRegexError(e)); } }; Ok(RegexFeature { @@ -1180,8 +1203,11 @@ impl RegexFeature { let mut ll = vec![]; for (feature, locations) in features { if let Feature::String(s) = feature { - if self.re.find(s.value.as_bytes()).is_some() { + if let Ok(Some(_)) = self.re.find(s.value.as_bytes()) { + // eprintln!("true {}\t{}", self.re.as_str(), s.value); ll.extend(locations); + } else { + // eprintln!("false {}\t{}", self.re.as_str(), s.value); } } } diff --git a/src/rules/mod.rs b/src/rules/mod.rs index d7b4e3f..9faf2f3 100644 --- a/src/rules/mod.rs +++ b/src/rules/mod.rs @@ -10,8 +10,15 @@ use statement::{ use std::collections::HashMap; use yaml_rust::{yaml::Hash, Yaml, YamlLoader}; +use self::features::ComType; + const MAX_BYTES_FEATURE_SIZE: usize = 0x100; +fn translate_com_features(_name: &str, _com_type: &ComType) -> Vec { + //TODO + vec![] +} + #[derive(Debug)] pub enum Value { Str(String), @@ -867,6 +874,31 @@ impl Rule { )) } } + } else if kkey.starts_with("com/") { + let com_type_name = &kkey["com/".len()..]; + let com_type: ComType = com_type_name.try_into()?; + let val = match &d[key] { + Yaml::String(s) => s.clone(), + Yaml::Integer(i) => i.to_string(), + _ => return Err(Error::InvalidRule(line!(), format!("{:?}", d[key]))), + }; + let description = match &d.get(&Yaml::String("description".to_string())) { + Some(Yaml::String(s)) => Some(s.clone()), + _ => None, + }; + let (value, description) = Rule::parse_description( + &val, + &RuleFeatureType::ComType(com_type.clone()), + &description, + )?; + let d = match description { + Some(s) => s, + _ => "".to_string(), + }; + let ff = translate_com_features(&value.get_str()?, &com_type); + return Ok(StatementElement::Statement(Box::new(Statement::Or( + OrStatement::new(ff, &d)?, + )))); } else { let feature_type = Rule::parse_feature_type(kkey)?; let val = match &d[key] {