diff --git a/volatility/framework/contexts/__init__.py b/volatility/framework/contexts/__init__.py index 699be67a5..0d18709d2 100644 --- a/volatility/framework/contexts/__init__.py +++ b/volatility/framework/contexts/__init__.py @@ -74,6 +74,7 @@ class Context(interfaces.context.ContextInterface): :rtype: :py:class:`volatility.framework.interfaces.objects.ObjectInterface` """ object_template = self._symbol_space.get_type(symbol) + object_template = object_template.clone() object_template.update_vol(**arguments) return object_template(context = self, object_info = interfaces.objects.ObjectInformation(layer_name = layer_name, diff --git a/volatility/framework/interfaces/objects.py b/volatility/framework/interfaces/objects.py index 1003f5601..b0e1ae682 100644 --- a/volatility/framework/interfaces/objects.py +++ b/volatility/framework/interfaces/objects.py @@ -89,6 +89,7 @@ class ObjectInterface(validity.ValidityRoutines, metaclass = ABCMeta): """Returns a new object at the offset and from the layer that the current object inhabits""" # TODO: Carefully consider the implications of casting and how it should work object_template = self._context.symbol_space.get_type(new_type_name) + object_template = object_template.clone() object_template.update_vol(**additional) object_info = ObjectInformation(layer_name = self.vol.layer_name, offset = self.vol.offset, @@ -132,7 +133,8 @@ class Template(validity.ValidityRoutines): """Stores the keyword arguments for later use""" # Allow the updating of template arguments whilst still in template form super().__init__() - self._vol = collections.ChainMap(arguments, {'type_name': type_name}) + self._arguments = arguments + self._vol = collections.ChainMap({}, self._arguments, {'type_name': type_name}) @property def vol(self): @@ -163,6 +165,11 @@ class Template(validity.ValidityRoutines): def replace_child(self, old_child, new_child): """A function for replacing one child with another""" + def clone(self): + """Returns a copy of the original Template as constructed (without update_vol having been called)""" + clone = self.__class__(**self._vol.parents.new_child()) + return clone + def update_vol(self, **new_arguments): """Updates the keyword arguments""" self._vol.update(new_arguments) diff --git a/volatility/framework/objects/templates.py b/volatility/framework/objects/templates.py index 510b51733..71b66449b 100644 --- a/volatility/framework/objects/templates.py +++ b/volatility/framework/objects/templates.py @@ -24,7 +24,7 @@ class ObjectTemplate(interfaces.objects.Template, validity.ValidityRoutines): def __init__(self, object_class = None, type_name = None, **arguments): super().__init__(type_name = type_name, **arguments) self._check_class(object_class, interfaces.objects.ObjectInterface) - self.update_vol(object_class = object_class) + self._arguments['object_class'] = object_class @property def size(self): diff --git a/volatility/framework/symbols/intermed.py b/volatility/framework/symbols/intermed.py index 0f726d0d6..afdb6bebc 100644 --- a/volatility/framework/symbols/intermed.py +++ b/volatility/framework/symbols/intermed.py @@ -204,7 +204,7 @@ class Version1Format(ISFormatTable): elif type_name == 'bitfield': update = {'start_bit': dictionary['bit_position'], 'end_bit': dictionary['bit_length']} update['base_type'] = self._interdict_to_template(dictionary['type']) - native_template.update_vol(**update) # pylint: disable=W0142 + native_template.update_vol(**update) return native_template # Otherwise