Attempt to standardize error message display.

This commit is contained in:
Mike Auty
2016-10-30 17:51:45 +00:00
parent f771de3703
commit 667014a1fd
14 changed files with 75 additions and 67 deletions
+12 -11
View File
@@ -33,19 +33,19 @@ def require_version(*args):
"""Checks the required version of a plugin"""
if len(args):
if args[0] != version()[0]:
raise RuntimeError("Framework version " + str(version()[0]) +
" is incompatible with required version " + str(args[0]))
raise RuntimeError(
"Framework version {} is incompatible with required version {}".format(version()[0], args[0]))
if len(args) > 1:
if args[1] > version()[1]:
raise RuntimeError("Framework version " + ".".join([str(x) for x in version()[0:1]]) +
" is an older revision than the required version " +
".".join([str(x) for x in args[0:2]]))
raise RuntimeError("Framework version {} is an older revision than the required version {}".format(
".".join([str(x) for x in version()[0:1]]),
".".join([str(x) for x in args[0:2]])))
def class_subclasses(cls):
"""Returns all the (recursive) subclasses of a given class"""
if not inspect.isclass(cls):
raise TypeError(repr(cls) + " is not a class.")
raise TypeError("class_subclasses parameter not a valid class: {}".format(cls))
for clazz in cls.__subclasses__():
yield clazz
for return_value in class_subclasses(clazz):
@@ -67,17 +67,18 @@ def import_files(base_module):
module = modpath.replace(os.path.sep, ".")
if module not in sys.modules:
try:
vollog.debug("Importing " + base_module.__name__ + "." + module)
vollog.debug("Importing module: {}.{}".format(base_module.__name__, module))
__import__(base_module.__name__ + "." + module)
except ImportError:
vollog.warning("Failed to import module " + module + " based on file " + modpath)
vollog.warning("Failed to import module {} based on file: {}".format(module, modpath))
raise
else:
vollog.info("Skipping existing module " + module)
vollog.info("Skipping existing module: {}".format(module))
# Check the python version to ensure it's suitable
if sys.version_info.major != 3 or sys.version_info.minor < 4:
raise RuntimeError("Volatility framework requires python version 3.4 or greater")
required_python_version = (3, 4)
if sys.version_info.major != required_python_version[0] or sys.version_info.minor < required_python_version[1]:
raise RuntimeError("Volatility framework requires python version {}.{} or greater".format(required_python_version))
from volatility.framework import interfaces, symbols, layers, contexts, configuration
@@ -22,7 +22,7 @@ class ConstructionMagic(interfaces.automagic.AutomagicInterface):
# We want to traverse optional paths, so don't check until we've tried to validate
# We also don't want to emit a debug message when a parent is optional, hence the optional parameter
if not valid and not (optional or subreq.optional):
vollog.debug("Failed on requirement: {0}".format(subreq_config_path))
vollog.debug("Failed on requirement: {}".format(subreq_config_path))
success = False
if not success:
return False
@@ -32,7 +32,9 @@ class InstanceRequirement(interfaces.configuration.RequirementInterface):
def validate(self, context, config_path):
value = self.config_value(context, config_path, None)
if not isinstance(value, self.instance_type):
vollog.debug("TypeError - " + self.name + " input only accepts " + self.instance_type.__name__ + " type")
vollog.debug(
"TypeError - {} requirements only accept {} type: {}".format(self.name, self.instance_type.__name__,
value))
return False
return True
@@ -29,7 +29,7 @@ class RequirementInterface(validity.ValidityRoutines, metaclass = ABCMeta):
super().__init__()
self._check_type(name, str)
if CONFIG_SEPARATOR in name:
raise ValueError("Name cannot contain the config-hierarchy divider (" + CONFIG_SEPARATOR + ")")
raise ValueError("Name cannot contain the config-hierarchy divider ({})".format(CONFIG_SEPARATOR))
self._name = name
self._description = description or ""
self._default = default
@@ -238,7 +238,7 @@ class ConfigurableInterface(validity.ValidityRoutines, metaclass = ABCMeta):
class HierarchicalDict(collections.Mapping):
def __init__(self, initial_dict = None, separator = CONFIG_SEPARATOR):
if not (isinstance(separator, str) and len(separator) == 1):
raise TypeError("Separator must be a one character string: {0}".format(separator))
raise TypeError("Separator must be a one character string: {}".format(separator))
self._separator = separator
self._data = {}
self._subdict = {}
@@ -248,8 +248,8 @@ class HierarchicalDict(collections.Mapping):
for k, v in initial_dict.items():
self[k] = v
elif initial_dict is not None:
raise TypeError("Initial_dict must be a dictionary or JSON string containing a dictionary: {0}".format(
repr(initial_dict)))
raise TypeError("Initial_dict must be a dictionary or JSON string containing a dictionary: {}".format(
initial_dict))
@property
def separator(self):
@@ -315,7 +315,7 @@ class HierarchicalDict(collections.Mapping):
else:
if not isinstance(value, HierarchicalDict) and value is not None:
raise TypeError(
"HierarchicalDicts can only store HierarchicalDicts within their structure: {0}".format(
"HierarchicalDicts can only store HierarchicalDicts within their structure: {}".format(
type(value)))
self._subdict[key] = value
@@ -389,12 +389,12 @@ class TranslationLayerRequirement(ConstructableRequirementInterface):
value = self.config_value(context, config_path, None)
if isinstance(value, str):
if value not in context.memory:
vollog.debug("IndexError - Layer not found in memory space: {0}".format(value))
vollog.debug("IndexError - Layer not found in memory space: {}".format(value))
return False
return True
if value is not None:
vollog.debug("TypeError - Translation Layer Requirement only accepts string labels: {0}".format(value))
vollog.debug("TypeError - Translation Layer Requirement only accepts string labels: {}".format(value))
return False
# TODO: check that the space in the context lives up to the requirements for arch/os etc
@@ -402,7 +402,7 @@ class TranslationLayerRequirement(ConstructableRequirementInterface):
### NOTE: This validate method has side effects (the dependencies can change)!!!
self._check_class(context, config_path)
vollog.debug("IndexError - No configuration provided: {0}".format(config_path + CONFIG_SEPARATOR + self.name))
vollog.debug("IndexError - No configuration provided: {}".format(config_path + CONFIG_SEPARATOR + self.name))
return False
def construct(self, context, config_path):
@@ -438,11 +438,11 @@ class SymbolRequirement(ConstructableRequirementInterface):
"""Validate that the value is a valid within the symbol space of the provided context"""
value = self.config_value(context, config_path, None)
if not isinstance(value, str):
vollog.debug("TypeError - SymbolRequirement only accepts string labels: {0}".format(value))
vollog.debug("TypeError - SymbolRequirement only accepts string labels: {}".format(value))
return False
if value not in context.symbol_space:
# This is an expected situation, so return False rather than raise
vollog.debug("IndexError - Value not present in the symbol space: {0}".format(value or ""))
vollog.debug("IndexError - Value not present in the symbol space: {}".format(value or ""))
return False
return True
+9 -9
View File
@@ -188,8 +188,8 @@ class TranslationLayerInterface(DataLayerInterface, metaclass = ABCMeta):
for (offset, mapped_offset, length, layer) in self.mapping(offset, length, ignore_errors = pad):
if not pad and offset > current_offset:
raise exceptions.InvalidAddressException(self.name, current_offset,
"Layer " + self.name + " cannot map offset " +
str(current_offset))
"Layer {} cannot map offset: {}".format(self.name,
current_offset))
elif offset > current_offset:
output += [b"\x00" * (current_offset - offset)]
current_offset = offset
@@ -207,8 +207,8 @@ class TranslationLayerInterface(DataLayerInterface, metaclass = ABCMeta):
for (offset, mapped_offset, length, layer) in self.mapping(offset, length):
if offset > current_offset:
raise exceptions.InvalidAddressException(self.name, current_offset,
"Layer " + self.name + " cannot map offset " +
str(current_offset))
"Layer {} cannot map offset: {}".format(self.name,
current_offset))
elif offset < current_offset:
raise exceptions.LayerException("Mapping returned an overlapping element")
self._context.memory.write(layer, mapped_offset, length)
@@ -261,11 +261,11 @@ class Memory(validity.ValidityRoutines, collections.abc.Mapping):
self._check_type(layer, DataLayerInterface)
if isinstance(layer, TranslationLayerInterface):
if layer.name in self._layers:
raise exceptions.LayerException("Layer " + layer.name + " already exists.")
raise exceptions.LayerException("Layer already exists: {}".format(layer.name))
missing_list = [sublayer for sublayer in layer.dependencies if sublayer not in self._layers]
if missing_list:
raise exceptions.LayerException("Layer " + layer.name +
" has unmet dependencies of " + ", ".join(missing_list) + ".")
raise exceptions.LayerException(
"Layer {} has unmet dependencies: {}".format(layer.name, ", ".join(missing_list)))
self._layers[layer.name] = layer
def del_layer(self, name):
@@ -276,8 +276,8 @@ class Memory(validity.ValidityRoutines, collections.abc.Mapping):
for layer in self._layers:
depend_list = [superlayer for superlayer in self._layers if name in superlayer.dependencies]
if depend_list:
raise exceptions.LayerException("Layer " + layer.name +
" is depended upon by " + ", ".join(depend_list))
raise exceptions.LayerException(
"Layer {} is depended upon: {}".format(layer.name, ", ".join(depend_list)))
self._layers[name].destroy()
del self._layers[name]
+2 -2
View File
@@ -22,7 +22,7 @@ class ReadOnlyMapping(validity.ValidityRoutines, collections.abc.Mapping):
"""Returns the item as an attribute"""
if attr in self._dict:
return self._dict[attr]
raise AttributeError("'" + self.__class__.__name__ + "' object has no attribute '" + attr + '"')
raise AttributeError("Object has no attribute: {}.{}".format(self.__class__.__name__, attr))
def __getitem__(self, name):
"""Returns the item requested"""
@@ -112,7 +112,7 @@ class ObjectInterface(validity.ValidityRoutines, metaclass = ABCMeta):
@classmethod
def relative_child_offset(cls, template, child):
"""Returns the relative offset from the head of the parent data to the child member"""
raise KeyError(repr(template.vol.type_name) + " does not contain any children.")
raise KeyError("Template does not contain any children: {}".format(template.vol.type_name))
class Template(validity.ValidityRoutines):
+1 -1
View File
@@ -12,7 +12,7 @@ class Symbol(validity.ValidityRoutines):
def __init__(self, name, address, type_name = None):
self._name = self._check_type(name, str)
if constants.BANG in self._name:
raise ValueError("Symbol names cannot contain the symbol differentiator (" + constants.BANG + ")")
raise ValueError("Symbol names cannot contain the symbol differentiator ({})".format(constants.BANG))
self._location = None
self._address = self._check_type(address, int)
if type_name is None:
+6 -5
View File
@@ -63,7 +63,8 @@ class LimeLayer(interfaces.layers.TranslationLayerInterface):
start, end = self._check_header(base_layer, offset)
if start < maxaddr or end < start:
raise LimeFormatException("bad start/end 0x%x/0x%x at file offset 0x%x" % (start, end, offset))
raise LimeFormatException(
"bad start/end 0x{:x}/0x{:x} at file offset 0x{:x}".format(start, end, offset))
segment_length = end - start + 1
segments.append((start, offset + header_size, segment_length))
@@ -71,7 +72,7 @@ class LimeLayer(interfaces.layers.TranslationLayerInterface):
offset = offset + header_size + segment_length
if len(segments) == 0:
raise LimeFormatException("No LiME segments defined in " + self._base_layer)
raise LimeFormatException("No LiME segments defined in {}".format(self._base_layer))
self._segments = segments
self._minaddr = segments[0][0]
@@ -82,9 +83,9 @@ class LimeLayer(interfaces.layers.TranslationLayerInterface):
header_data = base_layer.read(offset, cls._header_struct.size)
(magic, version, start, end, reserved) = cls._header_struct.unpack(header_data)
if magic != cls.MAGIC:
raise LimeFormatException("bad magic 0x%x at file offset 0x%x" % (magic, offset))
raise LimeFormatException("bad magic 0x{:x} at file offset 0x{:x}".format(magic, offset))
if version != cls.VERSION:
raise LimeFormatException("unexpected version %d at file offset 0x%x" % (version, offset))
raise LimeFormatException("unexpected version {:d} at file offset 0x{:x}".format(version, offset))
return start, end
def _find_segment(self, offset):
@@ -100,7 +101,7 @@ class LimeLayer(interfaces.layers.TranslationLayerInterface):
if offset >= logical_start and offset < (logical_start + size):
return (logical_start, base_start, size)
raise exceptions.InvalidAddressException(self.name, offset, "Lime fault at address " + hex(offset))
raise exceptions.InvalidAddressException(self.name, offset, "Lime fault at address {:0x}".format(offset))
def is_valid(self, offset, length = 1):
"""Returns whether the address offset can be translated to a valid address"""
+8 -7
View File
@@ -19,7 +19,7 @@ class Void(interfaces.objects.ObjectInterface):
@classmethod
def size(cls, template):
"""Dummy size for Void objects"""
raise TypeError("Void types are incomplete, cannot contain data and do not have a size.")
raise TypeError("Void types are incomplete, cannot contain data and do not have a size")
def write(self, value):
"""Dummy method that does nothing for Void objects"""
@@ -70,8 +70,9 @@ class PrimitiveObject(interfaces.objects.ObjectInterface):
if isinstance(value, self._struct_type):
data = struct.pack(self.vol.struct_format, value)
return self._context.memory.write(self.vol.layer_name, self.vol.offset, data)
raise TypeError(
repr(self.__class__.__name__) + " objects require a " + repr(type(self._struct_type)) + " to be written")
raise TypeError("Object {} requires a valid {} to be written: {}".format(self.__class__.__name__,
type(self._struct_type),
type(value)))
class Integer(PrimitiveObject, int):
@@ -267,7 +268,7 @@ class Array(interfaces.objects.ObjectInterface, collections.Sequence):
"""Returns the relative offset from the head of the parent data to the child member"""
if 'subtype' in template and child == 'subtype':
return 0
raise IndexError("Member " + child + " not present in array template")
raise IndexError("Member not present in array template: {}".format(child))
def __getitem__(self, i):
"""Returns the i-th item from the array"""
@@ -331,7 +332,7 @@ class Struct(interfaces.objects.ObjectInterface):
"""Returns the relative offset of a child to its parent"""
retlist = template.vol.members.get(child, None)
if retlist is None:
raise IndexError("Member " + child + " not present in template")
raise IndexError("Member not present in template: {}".format(child))
return retlist[0]
@classmethod
@@ -339,7 +340,7 @@ class Struct(interfaces.objects.ObjectInterface):
# Members should be an iterable mapping of symbol names to tuples of (relative_offset, ObjectTemplate)
# An object template is a callable that when called with a context, offset, layer_name and type_name
if not isinstance(members, collections.Mapping):
raise TypeError("Struct members parameter must be a mapping not " + type(members))
raise TypeError("Struct members parameter must be a mapping: {}".format(type(members)))
if not all([(isinstance(member, tuple) and len(member) == 2) for member in members.values()]):
raise TypeError("Struct members must be a tuple of relative_offsets and templates")
@@ -360,7 +361,7 @@ class Struct(interfaces.objects.ObjectInterface):
parent = self))
self._concrete_members[attr] = member
return member
raise AttributeError("'" + self.vol.type_name + "' Struct has no attribute '" + attr + "'")
raise AttributeError("Struct has no attribute: {}.{}".format(self.vol.type_name, attr))
def write(self, value):
raise TypeError("Structs cannot be written to directly, individual members must be written instead")
+1 -1
View File
@@ -79,7 +79,7 @@ class ReferenceTemplate(interfaces.objects.Template):
"""Referenced symbols must be appropriately resolved before they can provide information such as size
This is because the size request has no context within which to determine the actual symbol structure.
"""
raise SymbolError("Template {0} contains no information about its structure".format(self.vol.type_name))
raise SymbolError("Template contains no information about its structure: {}".format(self.vol.type_name))
size = property(_unresolved)
replace_child = relative_child_offset = _unresolved
+9 -7
View File
@@ -20,7 +20,7 @@ class TreeNode(interfaces.renderers.TreeNode):
self._values = treegrid.RowStructure(*values)
def __repr__(self):
return "<TreeNode [" + self._path + "] - " + repr(self._values) + ">"
return "<TreeNode [{}] - {}>".format(self.path, self._values)
def __getitem__(self, item):
return self._treegrid.children(self).__getitem__(item)
@@ -37,9 +37,11 @@ class TreeNode(interfaces.renderers.TreeNode):
column = self._treegrid.columns[index]
if not isinstance(values[index], column.type):
raise TypeError(
"Values item with index " + repr(index) + " is the wrong type for column " +
repr(column.name) + " (got " + str(type(values[index])) + " but expected " +
str(column.type) + ")")
"Values item with index {} is the wrong type for column {} (got {} but expected {})".format(
index,
column.name,
type(values[index]),
column.type))
@property
def values(self):
@@ -113,8 +115,8 @@ class TreeGrid(interfaces.renderers.TreeGrid):
for stype in self.simple_types:
is_simple_type = is_simple_type or issubclass(column_type, stype)
if not is_simple_type:
raise TypeError("Column " + name + "'s type " + column_type.__class__.__name__ +
" is not a simple type")
raise TypeError(
"Column {}'s type is not a simple type: {}".format(name, column_type.__class__.__name__))
converted_columns.append(interfaces.renderers.Column(len(converted_columns), name, column_type))
self.RowStructure = collections.namedtuple("RowStructure",
[self._sanitize(column.name) for column in converted_columns])
@@ -263,7 +265,7 @@ class ColumnSortKey(interfaces.renderers.ColumnSortKey):
if i.name.lower() == column_name.lower():
self._index = i.index
if self._index is None:
raise ValueError("Column " + column_name + " not found in TreeGrid columns")
raise ValueError("Column not found in TreeGrid columns: {}".format(column_name))
def key(self, values):
"""The key function passed as the sort key"""
+2 -2
View File
@@ -112,7 +112,7 @@ class SymbolSpace(collections.abc.Mapping):
"""
def __init__(self, type_name = None, **kwargs):
vollog.debug("Unresolved symbol referenced: {0}".format(type_name))
vollog.debug("Unresolved symbol referenced: {}".format(type_name))
super().__init__(type_name = type_name, **kwargs)
def _weak_resolve(self, resolve_type, name):
@@ -134,7 +134,7 @@ class SymbolSpace(collections.abc.Mapping):
return self._UnresolvedTemplate(name)
elif name in self.natives.types:
return getattr(self.natives, get_function)(name)
raise exceptions.SymbolError("Malformed symbol name: " + repr(name))
raise exceptions.SymbolError("Malformed symbol name: {}".format(name))
def get_type(self, type_name):
"""Takes a symbol name and resolves it
+8 -7
View File
@@ -15,7 +15,8 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface):
super().__init__(name, native_types)
url = urllib.parse.urlparse(idd_filepath)
if url.scheme != 'file':
raise NotImplementedError("The {0} scheme is not yet implement for the Intermediate Symbol Format.")
raise NotImplementedError(
"This scheme is not yet implement for the Intermediate Symbol Format: {}".format(url.scheme))
with open(url.path, "r") as fp:
self._json = json.load(fp)
self._validate_json()
@@ -36,7 +37,7 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface):
"""Returns the location offset given by the symbol name"""
symbol = self._json['symbols'].get(name, None)
if not symbol:
raise KeyError("Unknown symbol: {0}".format(name))
raise KeyError("Unknown symbol: {}".format(name))
return interfaces.symbols.Symbol(name = name, address = symbol['address'])
@property
@@ -53,7 +54,7 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface):
def set_type_class(self, name, clazz):
if name not in self.types:
raise ValueError("Symbol type " + name + " not in " + self.name + " SymbolTable")
raise ValueError("Symbol type not in {} SymbolTable: {}".format(self.name, name))
self._overrides[name] = clazz
def del_type_class(self, name):
@@ -68,7 +69,7 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface):
def _interdict_to_template(self, dictionary):
"""Converts an intermediate format dict into an object template"""
if not dictionary:
raise exceptions.SymbolSpaceError("Invalid intermediate dictionary: " + repr(dictionary))
raise exceptions.SymbolSpaceError("Invalid intermediate dictionary: {}".format(dictionary))
type_name = dictionary['kind']
if type_name == 'base':
@@ -95,7 +96,7 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface):
# Otherwise
if dictionary['kind'] not in ['struct', 'union']:
raise exceptions.SymbolSpaceError("Unknown Intermediate format: " + repr(dictionary))
raise exceptions.SymbolSpaceError("Unknown Intermediate format: {}".format(dictionary))
return objects.templates.ReferenceTemplate(type_name = self.name + constants.BANG + dictionary['name'])
@@ -103,7 +104,7 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface):
"""Looks up an enumeration and returns a dictionary of __init__ parameters for an Enum"""
lookup = self._json['enums'].get(name, None)
if not lookup:
raise exceptions.SymbolSpaceError("Unknown enumeration found: " + repr(name))
raise exceptions.SymbolSpaceError("Unknown enumeration found: {}".format(name))
result = {"choices": copy.deepcopy(lookup['constants']),
"subtype": self.natives.get_type(lookup['base'])}
return result
@@ -111,7 +112,7 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface):
def get_type(self, type_name):
"""Resolves an individual symbol"""
if type_name not in self._json['user_types']:
raise exceptions.SymbolError("Unknown symbol:" + repr(type_name))
raise exceptions.SymbolError("Unknown symbol: {}".format(type_name))
curdict = self._json['user_types'][type_name]
members = {}
for member_name in curdict['fields']:
+3 -3
View File
@@ -55,7 +55,7 @@ class VTypeSymbolTable(interfaces.symbols.SymbolTableInterface):
def set_type_class(self, name, clazz):
if name not in self.types:
raise ValueError("Symbol type " + name + " not in " + self.name + " SymbolTable")
raise ValueError("Unknown Symbol type: {}.{}".format(self.name, name))
self._overrides[name] = clazz
def del_type_class(self, name):
@@ -65,7 +65,7 @@ class VTypeSymbolTable(interfaces.symbols.SymbolTableInterface):
def _vtypedict_to_template(self, dictionary):
"""Converts a vtypedict into an object template"""
if not dictionary:
raise exceptions.SymbolSpaceError("Invalid vtype dictionary: " + repr(dictionary))
raise exceptions.SymbolSpaceError("Invalid vtype dictionary: {}".format(dictionary))
type_name = self._translate_vtype_to_intermed(dictionary[0])
@@ -91,7 +91,7 @@ class VTypeSymbolTable(interfaces.symbols.SymbolTableInterface):
# Otherwise
if len(dictionary) > 1:
raise exceptions.SymbolSpaceError("Unknown vtype format: " + repr(dictionary))
raise exceptions.SymbolSpaceError("Unknown vtype format: {}".format(dictionary))
return objects.templates.ReferenceTemplate(type_name = self.name + constants.BANG + type_name)