Skip to content

Commit

Permalink
Merge pull request #438 from oasis-open/issue_437
Browse files Browse the repository at this point in the history
hack for issue_435

Fixes #435.
  • Loading branch information
clenk authored Aug 7, 2020
2 parents 1f9a844 + 8f76a84 commit 1948b38
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 7 deletions.
19 changes: 15 additions & 4 deletions stix2/pattern_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import importlib
import inspect
from six import text_type

from stix2patterns.exceptions import ParseException
from stix2patterns.grammars.STIXPatternParser import TerminalNode
Expand Down Expand Up @@ -50,7 +51,7 @@ def check_for_valid_timetamp_syntax(timestamp_string):


def same_boolean_operator(current_op, op_token):
return current_op == op_token.symbol.text
return current_op == op_token.getText()


class STIXPatternVisitorForSTIX2():
Expand Down Expand Up @@ -259,6 +260,11 @@ def visitObjectPath(self, ctx):
if isinstance(next, TerminalNode):
property_path.append(self.instantiate("ListObjectPathComponent", current.property_name, next.getText()))
i += 2
elif isinstance(next, IntegerConstant):
property_path.append(self.instantiate("ListObjectPathComponent",
current.property_name if isinstance(current, BasicObjectPathComponent) else text_type(current),
next.value))
i += 2
else:
property_path.append(current)
i += 1
Expand All @@ -272,7 +278,12 @@ def visitObjectType(self, ctx):
# Visit a parse tree produced by STIXPatternParser#firstPathComponent.
def visitFirstPathComponent(self, ctx):
children = self.visitChildren(ctx)
step = children[0].getText()
first_component = children[0]
# hack for when the first component isn't a TerminalNode (see issue #438)
if isinstance(first_component, TerminalNode):
step = first_component.getText()
else:
step = text_type(first_component)
# if step.endswith("_ref"):
# return stix2.ReferenceObjectPathComponent(step)
# else:
Expand All @@ -291,8 +302,8 @@ def visitPathStep(self, ctx):
def visitKeyPathStep(self, ctx):
children = self.visitChildren(ctx)
if isinstance(children[1], StringConstant):
# special case for hashes
return children[1].value
# special case for hashes and quoted steps
return children[1]
else:
return self.instantiate("BasicObjectPathComponent", children[1].getText(), True)

Expand Down
5 changes: 4 additions & 1 deletion stix2/patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,10 @@ def make_constant(value):
class _ObjectPathComponent(object):
@staticmethod
def create_ObjectPathComponent(component_name):
if component_name.endswith("_ref"):
# first case is to handle if component_name was quoted
if isinstance(component_name, StringConstant):
return BasicObjectPathComponent(component_name.value, False)
elif component_name.endswith("_ref"):
return ReferenceObjectPathComponent(component_name)
elif component_name.find("[") != -1:
parse1 = component_name.split("[")
Expand Down
20 changes: 18 additions & 2 deletions stix2/test/v20/test_pattern_expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,15 +512,31 @@ def test_parsing_start_stop_qualified_expression():


def test_parsing_mixed_boolean_expression_1():
patt_obj = create_pattern_object("[a:b = 1 AND a:b = 2 OR a:b = 3]",)
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]",)
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_integer_index():
patt_obj = create_pattern_object("[a:b[1]=2]")
assert str(patt_obj) == "[a:b[1] = 2]"


# This should never occur, because the first component will always be a property_name, and they should not be quoted.
def test_parsing_quoted_first_path_component():
patt_obj = create_pattern_object("[a:'b'[1]=2]")
assert str(patt_obj) == "[a:'b'[1] = 2]"


def test_parsing_quoted_second_path_component():
patt_obj = create_pattern_object("[a:b.'b'[1]=2]")
assert str(patt_obj) == "[a:b.'b'[1] = 2]"


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")
Expand Down
15 changes: 15 additions & 0 deletions stix2/test/v21/test_pattern_expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,21 @@ def test_parsing_mixed_boolean_expression_2():
assert str(patt_obj) == "[a:b = 1 OR a:b = 2 AND a:b = 3]"


def test_parsing_integer_index():
patt_obj = create_pattern_object("[a:b[1]=2]")
assert str(patt_obj) == "[a:b[1] = 2]"

# This should never occur, because the first component will always be a property_name, and they should not be quoted.
def test_parsing_quoted_first_path_component():
patt_obj = create_pattern_object("[a:'b'[1]=2]")
assert str(patt_obj) == "[a:'b'[1] = 2]"


def test_parsing_quoted_second_path_component():
patt_obj = create_pattern_object("[a:b.'b'[1]=2]")
assert str(patt_obj) == "[a:b.'b'[1] = 2]"


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\\'']"
Expand Down

0 comments on commit 1948b38

Please sign in to comment.