Avoid checking valid refs when deepcopying

Using `deepcopy` on an Observable object that referenced another (e.g.
domain name -> resolves to -> IPv4 address) would fail because no
`_valid_refs` were available. Assuming that the references have
already been checked and are valid when using `deepcopy`, we can use a
special value ('*') to skip the valid_refs check.

This will also allow creating new versions of ObservedData objects that
contain related objects, since `new_version` calls `deepcopy`.
stix2.0
Chris Lenk 2018-02-19 14:44:28 -05:00
parent a790d8f561
commit 845934033e
2 changed files with 29 additions and 1 deletions

View File

@ -161,9 +161,12 @@ class _STIXBase(collections.Mapping):
", ".join(["{0!s}={1!r}".format(k, v) for k, v in props]))
def __deepcopy__(self, memo):
# Assumption: we can ignore the memo argument, because no object will ever contain the same sub-object multiple times.
# Assume: we can ignore the memo argument, because no object will ever contain the same sub-object multiple times.
new_inner = copy.deepcopy(self._inner, memo)
cls = type(self)
if isinstance(self, _Observable):
# Assume: valid references in the original object are still valid in the new version
new_inner['_valid_refs'] = {'*': '*'}
return cls(**new_inner)
def properties_populated(self):
@ -221,6 +224,9 @@ class _Observable(_STIXBase):
super(_Observable, self).__init__(**kwargs)
def _check_ref(self, ref, prop, prop_name):
if '*' in self._STIXBase__valid_refs:
return # don't check if refs are valid
if ref not in self._STIXBase__valid_refs:
raise InvalidObjRefError(self.__class__, prop_name, "'%s' is not a valid object in local scope" % ref)

View File

@ -1162,3 +1162,25 @@ def test_x509_certificate_example():
assert x509.type == "x509-certificate"
assert x509.issuer == "C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/emailAddress=server-certs@thawte.com" # noqa
assert x509.subject == "C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org/emailAddress=baccala@freesoft.org" # noqa
def test_new_version_with_related_objects():
data = stix2.ObservedData(
first_observed="2016-03-12T12:00:00Z",
last_observed="2016-03-12T12:00:00Z",
number_observed=1,
objects={
'src_ip': {
'type': 'ipv4-addr',
'value': '127.0.0.1/32'
},
'domain':{
'type': 'domain-name',
'value': 'example.com',
'resolves_to_refs': ['src_ip']
}
}
)
new_version = data.new_version(last_observed="2017-12-12T12:00:00Z")
assert new_version.last_observed.year == 2017
assert new_version.objects['domain'].resolves_to_refs[0] == 'src_ip'