diff --git a/sigma/conversion/base.py b/sigma/conversion/base.py index 8fc9a7b4..eb1f82dc 100644 --- a/sigma/conversion/base.py +++ b/sigma/conversion/base.py @@ -779,6 +779,10 @@ class variables. If this is not sufficient, the respective methods can be implem None # All matches of this pattern are prepended with the string contained in field_escape. ) + # Characters to escape in addition in regular expression representation of string (regex + # template variable) to default escaping characters. + add_escaped_re: ClassVar[str] = "" + ## Values ### String quoting str_quote: ClassVar[str] = "" # string quoting character (added as escaping character) @@ -1340,7 +1344,7 @@ def convert_condition_field_eq_val_str( return expr.format( field=self.escape_and_quote_field(cond.field), value=self.convert_value_str(value, state), - regex=self.convert_value_re(value.to_regex(), state), + regex=self.convert_value_re(value.to_regex(self.add_escaped_re), state), backend=self, ) except TypeError: # pragma: no cover @@ -1390,7 +1394,7 @@ def convert_condition_field_eq_val_str_case_sensitive( return expr.format( field=self.escape_and_quote_field(cond.field), value=self.convert_value_str(value, state), - regex=self.convert_value_re(value.to_regex(), state), + regex=self.convert_value_re(value.to_regex(self.add_escaped_re), state), ) except TypeError: # pragma: no cover raise NotImplementedError( @@ -1567,7 +1571,7 @@ def convert_condition_val_str( """Conversion of value-only strings.""" return self.unbound_value_str_expression.format( value=self.convert_value_str(cond.value, state), - regex=self.convert_value_re(cond.value.to_regex(), state), + regex=self.convert_value_re(cond.value.to_regex(self.add_escaped_re), state), ) def convert_condition_val_num( diff --git a/sigma/types.py b/sigma/types.py index e0ec69d9..c465d3c7 100644 --- a/sigma/types.py +++ b/sigma/types.py @@ -572,14 +572,14 @@ def convert( ) return s - def to_regex(self) -> "SigmaRegularExpression": + def to_regex(self, custom_escaped: str = "") -> "SigmaRegularExpression": """Convert SigmaString into a regular expression.""" return SigmaRegularExpression( self.convert( escape_char="\\", wildcard_multi=".*", wildcard_single=".", - add_escaped=".*+?^$[](){}\\|", + add_escaped=".*+?^$[](){}\\|" + custom_escaped, ) ) diff --git a/tests/test_types.py b/tests/test_types.py index 665edea9..1ca55b60 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -389,16 +389,22 @@ def test_strings_convert_invalid_part(): def test_strings_to_regex(): - s = SigmaString("Test*Special?(Plain)[\\*\\?]") + s = SigmaString("Test*Special?(Plain)/[\\*\\?]") assert s.s == ( "Test", SpecialChars.WILDCARD_MULTI, "Special", SpecialChars.WILDCARD_SINGLE, - "(Plain)[*?]", + "(Plain)/[*?]", ) r = s.to_regex() - assert r.regexp == "Test.*Special.\\(Plain\\)\\[\\*\\?\\]" + assert r.regexp == "Test.*Special.\\(Plain\\)/\\[\\*\\?\\]" + + +def test_strings_to_regex_with_additional_escape_chars(): + s = SigmaString("Test*Special?(Plain)/[\\*\\?]") + r = s.to_regex("/") + assert r.regexp == "Test.*Special.\\(Plain\\)\\/\\[\\*\\?\\]" def test_string_index(sigma_string):