diff --git a/stix2/pattern_visitor.py b/stix2/pattern_visitor.py index 5b8300f..c4deb64 100644 --- a/stix2/pattern_visitor.py +++ b/stix2/pattern_visitor.py @@ -49,6 +49,9 @@ def check_for_valid_timetamp_syntax(timestamp_string): return _TIMESTAMP_RE.match(timestamp_string) +def same_boolean_operator(current_op, op_token): + return current_op == op_token.symbol.text + class STIXPatternVisitorForSTIX2(): classes = {} @@ -131,7 +134,7 @@ class STIXPatternVisitorForSTIX2(): if len(children) == 1: return children[0] else: - if isinstance(children[0], _BooleanExpression): + if isinstance(children[0], _BooleanExpression) and same_boolean_operator(children[0].operator, children[1]): children[0].operands.append(children[2]) return children[0] else: diff --git a/stix2/test/v20/test_pattern_expressions.py b/stix2/test/v20/test_pattern_expressions.py index a96d3b8..0e0a9ca 100644 --- a/stix2/test/v20/test_pattern_expressions.py +++ b/stix2/test/v20/test_pattern_expressions.py @@ -511,6 +511,16 @@ def test_parsing_start_stop_qualified_expression(): ) == "[ipv4-addr:value = '1.2.3.4'] START '2016-06-01T00:00:00Z' STOP '2017-03-12T08:30:00Z'" +def test_parsing_mixed_boolean_expression_1(): + patt_obj = create_pattern_object("[a:b = 1 AND a:b = 2 OR a:b = 3]",) + assert str(patt_obj) == "[a:b = 1 AND a:b = 2 OR a:b = 3]" + + +def test_parsing_mixed_boolean_expression_2(): + patt_obj = create_pattern_object("[a:b = 1 OR a:b = 2 AND a:b = 3]",) + assert str(patt_obj) == "[a:b = 1 OR a:b = 2 AND a:b = 3]" + + def test_parsing_illegal_start_stop_qualified_expression(): with pytest.raises(ValueError): create_pattern_object("[ipv4-addr:value = '1.2.3.4'] START '2016-06-01' STOP '2017-03-12T08:30:00Z'", version="2.0") diff --git a/stix2/test/v21/test_pattern_expressions.py b/stix2/test/v21/test_pattern_expressions.py index 8294a41..b574e05 100644 --- a/stix2/test/v21/test_pattern_expressions.py +++ b/stix2/test/v21/test_pattern_expressions.py @@ -644,6 +644,16 @@ def test_parsing_boolean(): assert str(patt_obj) == "[network-traffic:is_active = true]" +def test_parsing_mixed_boolean_expression_1(): + patt_obj = create_pattern_object("[a:b = 1 AND a:b = 2 OR a:b = 3]",) + assert str(patt_obj) == "[a:b = 1 AND a:b = 2 OR a:b = 3]" + + +def test_parsing_mixed_boolean_expression_2(): + patt_obj = create_pattern_object("[a:b = 1 OR a:b = 2 AND a:b = 3]",) + assert str(patt_obj) == "[a:b = 1 OR a:b = 2 AND a:b = 3]" + + def test_parsing_multiple_slashes_quotes(): patt_obj = create_pattern_object("[ file:name = 'weird_name\\'' ]", version="2.1") assert str(patt_obj) == "[file:name = 'weird_name\\'']"