From e43208d26a10f6fc6e355d9f00c02db95e443b4f Mon Sep 17 00:00:00 2001 From: Kostas Papakonstantinou Date: Mon, 25 Feb 2019 21:32:42 +0200 Subject: [PATCH 1/2] Fixes #93. When parsing meta rules add parentheses around them so ! applies to the rule before doing other operations --- oa/rules/meta.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/oa/rules/meta.py b/oa/rules/meta.py index d9e85ba2..34ee8fea 100644 --- a/oa/rules/meta.py +++ b/oa/rules/meta.py @@ -12,13 +12,13 @@ CONVERT = ( ("&&", " and "), ("||", " or "), - ("!", " not "), + ("!", " not ") ) # Simple protection against recursion, or infinite loops with the meta rules. MAX_RECURSION = 10 -_SUBRULE_P = Regex(r"([_a-zA-Z]\w*)(?=\W|$)") +_SUBRULE_P = Regex(r"((?:!\s*)?[_a-zA-Z]\w*)(?=\W|$)") class MetaRule(oa.rules.base.BaseRule): @@ -46,7 +46,7 @@ def postparsing(self, ruleset, _depth=0): return subrules = set(_SUBRULE_P.findall(self.rule)) - rule = _SUBRULE_P.sub(r"\1(msg)", self.rule) + rule = _SUBRULE_P.sub(r"(\1(msg))", self.rule) for operator, repl in CONVERT: rule = rule.replace(operator, repl) rule_match = "match = lambda msg: %s" % rule @@ -56,8 +56,9 @@ def postparsing(self, ruleset, _depth=0): oa.rules.base.BaseRule.postparsing(self, ruleset) for subrule_name in subrules: + clean_subrule_name = subrule_name.strip("! \t") try: - subrule = ruleset.get_rule(subrule_name) + subrule = ruleset.get_rule(clean_subrule_name) # Call any postparsing for this subrule to ensure that the rule # is usable. (For example when the meta rule references other # meta rules). @@ -66,7 +67,7 @@ def postparsing(self, ruleset, _depth=0): raise oa.errors.InvalidRule(self.name, "Undefined subrule " "referenced %r" % subrule_name) - self._location[subrule_name] = subrule.match + self._location[clean_subrule_name] = subrule.match exec(_code_obj, self._location) assert "match" in self._location From f17b5ae8d4562dcde8412b2d7a771b0d74dca8a3 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 1 Mar 2019 14:21:09 +0000 Subject: [PATCH 2/2] Added test using complex rules and +\!. Should help developement --- tests/functional/test_rules/test_meta.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/functional/test_rules/test_meta.py b/tests/functional/test_rules/test_meta.py index 28fad6f6..3d6aaa6c 100644 --- a/tests/functional/test_rules/test_meta.py +++ b/tests/functional/test_rules/test_meta.py @@ -86,3 +86,14 @@ def test_header_meta_rule_combined_match(self): "Please click this link: https://example.com and follow the instructions", config=config, score=9.0, symbols=["TEST_DKIM_AND_FROM", "TEST_FROM_AND_URL", "TEST_ALL_RULE"]) + + def test_header_meta_rule_combined_match_not_operator(self): + config = ("body __TEST_NOT_DIFFERENT /instructions/\n" + "body __TEST_NOT_DIFFERENT2 /follow/\n" + "meta TEST_ALL_RULE (((__TEST_NOT_DIFFERENT*5) +! (1*__TEST_NOT_DIFFERENT2))>1)\n" + "score TEST_ALL_RULE 5") + self.check_symbols("DKIM-Signature: TestDkim \n" + "From: test \n\n" + "Please click this link: https://example.com and follow the instructions", + config=config, + score=5.0, symbols=["TEST_ALL_RULE"])