Fix tests, add a loophole to allow custom content

The "loophole" occurs when an object contains an unregistered top-level
extension. Since it's unregistered we can't tell if any custom
properties on the object were defined in that extension so we assume
that they are.
pull/1/head
Chris Lenk 2021-06-14 17:34:06 -04:00
parent 2528077eb0
commit 94859a0daf
3 changed files with 18 additions and 34 deletions

View File

@ -69,7 +69,7 @@ class _STIXBase(collections.abc.Mapping):
return has_custom
# interproperty constraint methods
# inter-property constraint methods
def _check_mutually_exclusive_properties(self, list_of_properties, at_least_one=True):
current_properties = self.properties_populated()
@ -119,7 +119,7 @@ class _STIXBase(collections.abc.Mapping):
extra_kwargs = kwargs.keys() - self._properties.keys()
if extra_kwargs and issubclass(cls, stix2.v21._Extension):
extra_kwargs = [prop for prop in extra_kwargs if prop != 'extension_type']
extra_kwargs = {prop for prop in extra_kwargs if prop != 'extension_type'}
if extra_kwargs and not allow_custom:
ext_found = False
@ -136,12 +136,24 @@ class _STIXBase(collections.abc.Mapping):
if ext_found is False:
raise ExtraPropertiesError(cls, extra_kwargs)
if custom_props:
# loophole for custom_properties...
extension_toplevel_properties = set()
unregistered_top_level_extension = False
if 'extensions' in kwargs and not isinstance(self, stix2.v20._STIXBase20):
for ext_name, ext in kwargs['extensions'].items():
if ext.get('extension_type', '') == 'toplevel-property-extension':
registered_extensions = stix2.registry.STIX2_OBJ_MAPS['2.1'].get('extensions', {})
if ext_name in registered_extensions:
registered_ext_properties = registered_extensions[ext_name]._properties.keys()
extension_toplevel_properties.update(registered_ext_properties)
else:
unregistered_top_level_extension = True
if custom_props or unregistered_top_level_extension:
# loophole for custom_properties and unregistered top-level extensions...
allow_custom = True
all_custom_prop_names = extra_kwargs | custom_props.keys() - \
self._properties.keys()
all_custom_prop_names = (extra_kwargs | custom_props.keys()) - \
self._properties.keys() - extension_toplevel_properties
if all_custom_prop_names:
if not isinstance(self, stix2.v20._STIXBase20):
for prop_name in all_custom_prop_names:

View File

@ -537,20 +537,6 @@ def test_extension_property_invalid3():
assert result[1]
def test_extension_property_invalid_type():
ext_prop = ExtensionsProperty(spec_version="2.0")
with pytest.raises(CustomContentError) as excinfo:
ext_prop.clean(
{
'windows-pebinary-ext': {
'pe_type': 'exe',
},
},
False,
)
assert "Can't parse unknown extension" in str(excinfo.value)
def test_extension_at_least_one_property_constraint():
with pytest.raises(AtLeastOnePropertyError):
stix2.v20.TCPExt()

View File

@ -571,20 +571,6 @@ def test_extension_property_invalid3():
assert result[1]
def test_extension_property_invalid_type():
ext_prop = ExtensionsProperty(spec_version='2.1', enclosing_type='indicator')
with pytest.raises(CustomContentError) as excinfo:
ext_prop.clean(
{
'windows-pebinary-ext': {
'pe_type': 'exe',
},
},
False,
)
assert "Can't parse unknown extension" in str(excinfo.value)
def test_extension_at_least_one_property_constraint():
with pytest.raises(AtLeastOnePropertyError):
stix2.v21.TCPExt()