Repository: oasis-open/cti-python-stix2

Issue:
Pattern AST creation bug
Comparison expression ORs can get changed to ANDs:

```python
from stix2.pattern_visitor import create_pattern_object

ast = create_pattern_object(pattern="[a:b=1 AND a:b=2 OR a:b=3]")

print(ast)
```
produces
```
[a:b = 1 AND a:b = 2 AND a:b = 3]
```


Discussion:

Patch:
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:


Test patch:
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\\'']"