Core: Change all 3.5 type hints to variable annotations

This commit is contained in:
Mike Auty
2021-07-18 16:49:37 +01:00
parent 9f52a15734
commit 0d48261201
58 changed files with 150 additions and 147 deletions
+1 -1
View File
@@ -43,7 +43,7 @@ class WarningFindSpec(abc.MetaPathFinder):
raise Warning(warning)
warning_find_spec = [WarningFindSpec()] # type: List[abc.MetaPathFinder]
warning_find_spec: List[abc.MetaPathFinder] = [WarningFindSpec()]
sys.meta_path = warning_find_spec + sys.meta_path
# We point the volatility3.plugins __path__ variable at BOTH
+1 -1
View File
@@ -583,7 +583,7 @@ class CommandLine:
# Construct an argparse group
for requirement in configurable.get_requirements():
additional = {} # type: Dict[str, Any]
additional: Dict[str, Any] = {}
if not isinstance(requirement, interfaces.configuration.RequirementInterface):
raise TypeError("Plugin contains requirements that are not RequirementInterfaces: {}".format(
configurable.__name__))
+4 -4
View File
@@ -278,7 +278,7 @@ class PrettyTextRenderer(CLIRenderer):
accumulator.append((node.path_depth, line))
return accumulator
final_output = [] # type: List[Tuple[int, Dict[interfaces.renderers.Column, bytes]]]
final_output: List[Tuple[int, Dict[interfaces.renderers.Column, bytes]]] = []
if not grid.populated:
grid.populate(visitor, final_output)
else:
@@ -323,15 +323,15 @@ class JsonRenderer(CLIRenderer):
outfd = sys.stdout
outfd.write("\n")
final_output = (
{}, []) # type: Tuple[Dict[str, List[interfaces.renderers.TreeNode]], List[interfaces.renderers.TreeNode]]
final_output: Tuple[Dict[str, List[interfaces.renderers.TreeNode]], List[interfaces.renderers.TreeNode]] = (
{}, [])
def visitor(
node: interfaces.renderers.TreeNode, accumulator: Tuple[Dict[str, Dict[str, Any]], List[Dict[str, Any]]]
) -> Tuple[Dict[str, Dict[str, Any]], List[Dict[str, Any]]]:
# Nodes always have a path value, giving them a path_depth of at least 1, we use max just in case
acc_map, final_tree = accumulator
node_dict = {'__children': []} # type: Dict[str, Any]
node_dict: Dict[str, Any] = {'__children': []}
for column_index in range(len(grid.columns)):
column = grid.columns[column_index]
renderer = self._type_renderers.get(column.type, self._type_renderers['default'])
+3 -3
View File
@@ -12,7 +12,7 @@ from typing import List, Optional, Sequence, Any, Union
# We shouldn't really steal a private member from argparse, but otherwise we're just duplicating code
# HelpfulSubparserAction gives more information about the possible choices from a subparsed choice
# HelpfulArgParser gives the list of choices when no arguments are provided to a choice option whilst still using a METAVAR
# HelpfulArgParser gives the list of choices when no arguments are provided to a choice option whilst still using a
class HelpfulSubparserAction(argparse._SubParsersAction):
@@ -22,7 +22,7 @@ class HelpfulSubparserAction(argparse._SubParsersAction):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
# We don't want the action self-check to kick in, so we remove the choices list, the check happens in __call__
self.choices = None # type: ignore
self.choices = None
def __call__(self,
parser: argparse.ArgumentParser,
@@ -31,7 +31,7 @@ class HelpfulSubparserAction(argparse._SubParsersAction):
option_string: Optional[str] = None) -> None:
parser_name = ''
arg_strings = [] # type: List[str]
arg_strings: List[str] = []
if values is not None:
for value in values:
if not parser_name:
+2 -2
View File
@@ -30,7 +30,7 @@ class Volshell(interfaces.plugins.PluginInterface):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__current_layer = None # type: Optional[str]
self.__current_layer: Optional[str] = None
self.__console = None
def random_string(self, length: int = 32) -> str:
@@ -38,7 +38,7 @@ class Volshell(interfaces.plugins.PluginInterface):
@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
reqs = [] # type: List[interfaces.configuration.RequirementInterface]
reqs: List[interfaces.configuration.RequirementInterface] = []
if cls == Volshell:
reqs = [
requirements.URIRequirement(name = 'script',
@@ -37,7 +37,7 @@ class ConstructionMagic(interfaces.automagic.AutomagicInterface):
# Make sure we import the layers, so they can reconstructed
framework.import_files(sys.modules['volatility3.framework.layers'])
result = [] # type: List[str]
result: List[str] = []
if requirement.unsatisfied(context, config_path):
# Having called validate at the top level tells us both that we need to dig deeper
# but also ensures that TranslationLayerRequirements have got the correct subrequirements if their class is populated
+1 -1
View File
@@ -57,7 +57,7 @@ class LinuxIntelStacker(interfaces.automagic.StackerLayerInterface):
layer_name,
progress_callback = progress_callback)
layer_class = intel.Intel # type: Type
layer_class: Type = intel.Intel
if 'init_top_pgt' in table.symbols:
layer_class = intel.Intel32e
dtb_symbol_name = 'init_top_pgt'
+5 -5
View File
@@ -62,7 +62,7 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
A list of (layer_name, scan_results)
"""
sub_config_path = interfaces.configuration.path_join(config_path, requirement.name)
results = [] # type: List[str]
results: List[str] = []
if isinstance(requirement, requirements.TranslationLayerRequirement):
# Check for symbols in this layer
# FIXME: optionally allow a full (slow) scan
@@ -207,13 +207,13 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
"""Method for finding a suitable kernel offset based on a module
table."""
vollog.debug("Kernel base determination - searching layer module list structure")
valid_kernel = None # type: Optional[ValidKernelType]
valid_kernel: Optional[ValidKernelType] = None
# If we're here, chances are high we're in a Win10 x64 image with kernel base randomization
physical_layer_name = self.get_physical_layer_name(context, vlayer)
physical_layer = context.layers[physical_layer_name]
# TODO: On older windows, this might be \WINDOWS\system32\nt rather than \SystemRoot\system32\nt
results = physical_layer.scan(context, scanners.BytesScanner(pattern), progress_callback = progress_callback)
seen = set() # type: Set[int]
seen: Set[int] = set()
# Because this will launch a scan of the virtual layer, we want to be careful
for result in results:
# TODO: Identify the specific structure we're finding and document this a bit better
@@ -252,7 +252,7 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
"""Scans a virtual address."""
# Scan a few megs of the virtual space at the location to see if they're potential kernels
valid_kernel = None # type: Optional[ValidKernelType]
valid_kernel: Optional[ValidKernelType] = None
kernel_pdb_names = [bytes(name + ".pdb", "utf-8") for name in constants.windows.KERNEL_MODULE_NAMES]
virtual_layer_name = vlayer.name
@@ -295,7 +295,7 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
Returns:
A dictionary of valid kernels
"""
valid_kernel = None # type: Optional[ValidKernelType]
valid_kernel: Optional[ValidKernelType] = None
for virtual_layer_name in potential_layers:
vlayer = context.layers.get(virtual_layer_name, None)
if isinstance(vlayer, layers.intel.Intel):
@@ -26,15 +26,15 @@ class SymbolBannerCache(interfaces.automagic.AutomagicInterface):
# The user would run it eventually either way, but running it first means it can be used that run
priority = 0
os = None # type: Optional[str]
symbol_name = "banner_name" # type: str
banner_path = None # type: Optional[str]
os: Optional[str] = None
symbol_name: str = "banner_name"
banner_path: Optional[str] = None
@classmethod
def load_banners(cls) -> BannersType:
if not cls.banner_path:
raise ValueError("Banner_path not appropriately set")
banners = {} # type: BannersType
banners: BannersType = {}
if os.path.exists(cls.banner_path):
with open(cls.banner_path, "rb") as f:
# We use pickle over JSON because we're dealing with bytes objects
@@ -17,15 +17,15 @@ class SymbolFinder(interfaces.automagic.AutomagicInterface):
"""Symbol loader based on signature strings."""
priority = 40
banner_config_key = "banner" # type: str
banner_cache = None # type: Optional[Type[symbol_cache.SymbolBannerCache]]
symbol_class = None # type: Optional[str]
find_aslr = None # type: Optional[Callable]
banner_config_key: str = "banner"
banner_cache: Optional[Type[symbol_cache.SymbolBannerCache]] = None
symbol_class: Optional[str] = None
find_aslr: Optional[Callable] = None
def __init__(self, context: interfaces.context.ContextInterface, config_path: str) -> None:
super().__init__(context, config_path)
self._requirements = [] # type: List[Tuple[str, interfaces.configuration.RequirementInterface]]
self._banners = {} # type: symbol_cache.BannersType
self._requirements: List[Tuple[str, interfaces.configuration.RequirementInterface]] = []
self._banners: symbol_cache.BannersType = {}
@property
def banners(self) -> symbol_cache.BannersType:
+1 -1
View File
@@ -325,7 +325,7 @@ class WindowsIntelStacker(interfaces.automagic.StackerLayerInterface):
if arch not in ['Intel32', 'Intel64']:
return None
# Set the layer type
layer_type = intel.WindowsIntel # type: Type
layer_type: Type = intel.WindowsIntel
if arch == 'Intel64':
layer_type = intel.WindowsIntel32e
elif base_layer.metadata.get('pae', False):
@@ -36,13 +36,13 @@ class BooleanRequirement(interfaces.configuration.SimpleTypeRequirement):
class IntRequirement(interfaces.configuration.SimpleTypeRequirement):
"""A requirement type that contains a single integer."""
instance_type = int # type: ClassVar[Type]
instance_type: ClassVar[Type] = int
class StringRequirement(interfaces.configuration.SimpleTypeRequirement):
"""A requirement type that contains a single unicode string."""
# TODO: Maybe add string length limits?
instance_type = str # type: ClassVar[Type]
instance_type: ClassVar[Type] = str
class URIRequirement(StringRequirement):
@@ -53,7 +53,7 @@ class URIRequirement(StringRequirement):
class BytesRequirement(interfaces.configuration.SimpleTypeRequirement):
"""A requirement type that contains a byte string."""
instance_type = bytes # type: ClassVar[Type]
instance_type: ClassVar[Type] = bytes
class ListRequirement(interfaces.configuration.RequirementInterface):
@@ -83,9 +83,9 @@ class ListRequirement(interfaces.configuration.RequirementInterface):
super().__init__(*args, **kwargs)
if not issubclass(element_type, interfaces.configuration.BasicTypes):
raise TypeError("ListRequirements can only be populated with simple InstanceRequirements")
self.element_type = element_type # type: Type
self.min_elements = min_elements or 0 # type: int
self.max_elements = max_elements # type: Optional[int]
self.element_type: Type = element_type
self.min_elements: int = min_elements or 0
self.max_elements: Optional[int] = max_elements
def unsatisfied(self, context: interfaces.context.ContextInterface,
config_path: str) -> Dict[str, interfaces.configuration.RequirementInterface]:
@@ -397,7 +397,7 @@ class VersionRequirement(interfaces.configuration.RequirementInterface):
super().__init__(name = name, description = description, default = default, optional = optional)
if component is None:
raise TypeError("Component cannot be None")
self._component = component # type: Type[interfaces.configuration.VersionableInterface]
self._component: Type[interfaces.configuration.VersionableInterface] = component
if version is None:
raise TypeError("Version cannot be None")
self._version = version
+2 -2
View File
@@ -319,7 +319,7 @@ class ModuleCollection:
included in the deduplicated version
"""
new_modules = []
seen = set() # type: Set[str]
seen: Set[str] = set()
for mod in self._modules:
if mod.hash not in seen or mod.size == 0:
new_modules.append(mod)
@@ -334,7 +334,7 @@ class ModuleCollection:
@classmethod
def _generate_module_dict(cls, modules: List[SizedModule]) -> Dict[str, List[SizedModule]]:
result = {} # type: Dict[str, List[SizedModule]]
result: Dict[str, List[SizedModule]] = {}
for module in modules:
modlist = result.get(module.name, [])
modlist.append(module)
@@ -82,7 +82,7 @@ class AutomagicInterface(interfaces.configuration.ConfigurableInterface, metacla
A list of tuples containing the config_path, sub_config_path and requirement identifying the unsatisfied `Requirements`
"""
sub_config_path = interfaces.configuration.path_join(config_path, requirement_root.name)
results = [] # type: List[Tuple[str, interfaces.configuration.RequirementInterface]]
results: List[Tuple[str, interfaces.configuration.RequirementInterface]] = []
recurse = not shortcut
if isinstance(requirement_root, requirement_type):
if recurse or requirement_root.unsatisfied(context, config_path):
@@ -105,7 +105,7 @@ class StackerLayerInterface(metaclass = ABCMeta):
stack_order = 0
"""The order in which to attempt stacking, the lower the earlier"""
exclusion_list = [] # type: List[str]
exclusion_list: List[str] = []
"""The list operating systems/first-level plugin hierarchy that should exclude this stacker"""
@classmethod
@@ -79,8 +79,8 @@ class HierarchicalDict(collections.abc.Mapping):
if not (isinstance(separator, str) and len(separator) == 1):
raise TypeError(f"Separator must be a one character string: {separator}")
self._separator = separator
self._data = {} # type: Dict[str, ConfigSimpleType]
self._subdict = {} # type: Dict[str, 'HierarchicalDict']
self._data: Dict[str, ConfigSimpleType] = {}
self._subdict: Dict[str, 'HierarchicalDict'] = {}
if isinstance(initial_dict, str):
initial_dict = json.loads(initial_dict)
if isinstance(initial_dict, dict):
@@ -320,7 +320,7 @@ class RequirementInterface(metaclass = ABCMeta):
self._description = description or ""
self._default = default
self._optional = optional
self._requirements = {} # type: Dict[str, RequirementInterface]
self._requirements: Dict[str, RequirementInterface] = {}
def __repr__(self) -> str:
return "<" + self.__class__.__name__ + ": " + self.name + ">"
@@ -438,7 +438,7 @@ class RequirementInterface(metaclass = ABCMeta):
class SimpleTypeRequirement(RequirementInterface):
"""Class to represent a single simple type (such as a boolean, a string, an
integer or a series of bytes)"""
instance_type = bool # type: ClassVar[Type]
instance_type: ClassVar[Type] = bool
def add_requirement(self, requirement: RequirementInterface):
"""Always raises a TypeError as instance requirements cannot have
@@ -529,7 +529,7 @@ class ConstructableRequirementInterface(RequirementInterface):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.add_requirement(ClassRequirement("class", "Class of the constructable requirement"))
self._current_class_requirements = set() # type: Set[Any]
self._current_class_requirements: Set[Any] = set()
def __eq__(self, other):
# We can just use super because it checks all member of `__dict__`
@@ -620,7 +620,7 @@ class ConfigurableInterface(metaclass = ABCMeta):
super().__init__()
self._context = context
self._config_path = config_path
self._config_cache = None # type: Optional[HierarchicalDict]
self._config_cache: Optional[HierarchicalDict] = None
@property
def context(self) -> 'interfaces.context.ContextInterface':
@@ -729,7 +729,7 @@ class VersionableInterface:
All version number should use semantic versioning
"""
_version = (0, 0, 0) # type: Tuple[int, int, int]
_version: Tuple[int, int, int] = (0, 0, 0)
@classproperty
def version(cls) -> Tuple[int, int, int]:
+9 -9
View File
@@ -58,8 +58,8 @@ class ScannerInterface(interfaces.configuration.VersionableInterface, metaclass
super().__init__()
self.chunk_size = 0x1000000 # Default to 16Mb chunks
self.overlap = 0x1000 # A page of overlap by default
self._context = None # type: Optional[interfaces.context.ContextInterface]
self._layer_name = None # type: Optional[str]
self._context: Optional[interfaces.context.ContextInterface] = None
self._layer_name: Optional[str] = None
@property
def context(self) -> Optional['interfaces.context.ContextInterface']:
@@ -99,7 +99,7 @@ class DataLayerInterface(interfaces.configuration.ConfigurableInterface, metacla
accesses a data source and exposes it within volatility.
"""
_direct_metadata = {'architecture': 'Unknown', 'os': 'Unknown'} # type: Mapping
_direct_metadata: Mapping = {'architecture': 'Unknown', 'os': 'Unknown'}
def __init__(self,
context: 'interfaces.context.ContextInterface',
@@ -227,7 +227,7 @@ class DataLayerInterface(interfaces.configuration.ConfigurableInterface, metacla
sections = list(self._coalesce_sections(sections))
try:
progress = DummyProgress() # type: ProgressValue
progress: ProgressValue = DummyProgress()
scan_iterator = functools.partial(self._scan_iterator, scanner, sections)
scan_metric = self._scan_metric(scanner, sections)
if not scanner.thread_safe or constants.PARALLELISM == constants.Parallelism.Off:
@@ -240,7 +240,7 @@ class DataLayerInterface(interfaces.configuration.ConfigurableInterface, metacla
yield from scan_chunk(value)
else:
progress = multiprocessing.Manager().Value("Q", 0)
parallel_module = multiprocessing # type: types.ModuleType
parallel_module: types.ModuleType = multiprocessing
if constants.PARALLELISM == constants.Parallelism.Threading:
progress = DummyProgress()
parallel_module = threading
@@ -266,7 +266,7 @@ class DataLayerInterface(interfaces.configuration.ConfigurableInterface, metacla
def _coalesce_sections(self, sections: Iterable[Tuple[int, int]]) -> Iterable[Tuple[int, int]]:
"""Take a list of (start, length) sections and coalesce any adjacent
sections."""
result = [] # type: List[Tuple[int, int]]
result: List[Tuple[int, int]] = []
position = 0
for (start, length) in sorted(sections):
if result and start <= position:
@@ -423,7 +423,7 @@ class TranslationLayerInterface(DataLayerInterface, metaclass = ABCMeta):
"""Reads an offset for length bytes and returns 'bytes' (not 'str') of
length size."""
current_offset = offset
output = b'' # type: bytes
output: bytes = b''
for (layer_offset, sublength, mapped_offset, mapped_length, layer) in self.mapping(offset,
length,
ignore_errors = pad):
@@ -473,7 +473,7 @@ class TranslationLayerInterface(DataLayerInterface, metaclass = ABCMeta):
assumed to have no holes
"""
for (section_start, section_length) in sections:
output = [] # type: List[Tuple[str, int, int]]
output: List[Tuple[str, int, int]] = []
# Hold the offsets of each chunk (including how much has been filled)
chunk_start = chunk_position = 0
@@ -532,7 +532,7 @@ class LayerContainer(collections.abc.Mapping):
"""Container for multiple layers of data."""
def __init__(self) -> None:
self._layers = {} # type: Dict[str, DataLayerInterface]
self._layers: Dict[str, DataLayerInterface] = {}
def read(self, layer: str, offset: int, length: int, pad: bool = False) -> bytes:
"""Reads from a particular layer at offset for length bytes.
+2 -2
View File
@@ -214,7 +214,7 @@ class ObjectInterface(metaclass = abc.ABCMeta):
to control how their templates respond without needing to write
new templates for each and every potental object type.
"""
_methods = [] # type: List[str]
_methods: List[str] = []
@classmethod
@abc.abstractmethod
@@ -275,7 +275,7 @@ class Template:
"""Stores the keyword arguments for later object creation."""
# Allow the updating of template arguments whilst still in template form
super().__init__()
empty_dict = {} # type: Dict[str, Any]
empty_dict: Dict[str, Any] = {}
self._vol = collections.ChainMap(empty_dict, arguments, {'type_name': type_name})
@property
+2 -2
View File
@@ -95,7 +95,7 @@ class PluginInterface(interfaces.configuration.ConfigurableInterface,
"""
# Be careful with inheritance around this (We default to requiring a version which doesn't exist, so it must be set)
_required_framework_version = (0, 0, 0) # type: Tuple[int, int, int]
_required_framework_version: Tuple[int, int, int] = (0, 0, 0)
"""The _version variable is a quick way for plugins to define their current interface, it should follow SemVer rules"""
def __init__(self,
@@ -121,7 +121,7 @@ class PluginInterface(interfaces.configuration.ConfigurableInterface,
if requirement.name not in self.config:
self.config[requirement.name] = requirement.default
self._file_handler = FileHandlerInterface # type: Type[FileHandlerInterface]
self._file_handler: Type[FileHandlerInterface] = FileHandlerInterface
framework.require_interface_version(*self._required_framework_version)
@@ -38,7 +38,7 @@ class Renderer(metaclass = ABCMeta):
class ColumnSortKey(metaclass = ABCMeta):
ascending = True # type: bool
ascending: bool = True
@abstractmethod
def __call__(self, values: List[Any]) -> Any:
@@ -129,7 +129,7 @@ class TreeGrid(object, metaclass = ABCMeta):
and to create cycles.
"""
base_types = (int, str, float, bytes, datetime.datetime, Disassembly) # type: ClassVar[Tuple]
base_types: ClassVar[Tuple] = (int, str, float, bytes, datetime.datetime, Disassembly)
def __init__(self, columns: ColumnsType, generator: Generator) -> None:
"""Constructs a TreeGrid object using a specific set of columns.
+1 -1
View File
@@ -96,7 +96,7 @@ class BaseSymbolTableInterface:
table_mapping = {}
self.table_mapping = table_mapping
self._native_types = native_types
self._sort_symbols = [] # type: List[Tuple[int, str]]
self._sort_symbols: List[Tuple[int, str]] = []
# Set any provisioned class_types
if class_types:
+1 -1
View File
@@ -39,7 +39,7 @@ class Intel(linear.LinearlyMappedLayer):
metadata: Optional[Dict[str, Any]] = None) -> None:
super().__init__(context = context, config_path = config_path, name = name, metadata = metadata)
self._base_layer = self.config["memory_layer"]
self._swap_layers = [] # type: List[str]
self._swap_layers: List[str] = []
self._page_map_offset = self.config["page_map_offset"]
# Assign constants
+2 -1
View File
@@ -33,7 +33,8 @@ class LinearlyMappedLayer(interfaces.layers.TranslationLayerInterface):
"""Reads an offset for length bytes and returns 'bytes' (not 'str') of
length size."""
current_offset = offset
output = [] # type: List[bytes]
output: List[bytes] = []
output: List[bytes] = []
for (offset, _, mapped_offset, mapped_length, layer) in self.mapping(offset, length, ignore_errors = pad):
if not pad and offset > current_offset:
raise exceptions.InvalidAddressException(
+1 -1
View File
@@ -34,7 +34,7 @@ class PdbMultiStreamFormat(linear.LinearlyMappedLayer):
if response is None:
raise PDBFormatException(name, "Could not find a suitable header")
self._version, self._header = response
self._streams = {} # type: Dict[int, str]
self._streams: Dict[int, str] = {}
@property
def pdb_symbol_table(self) -> str:
+3 -3
View File
@@ -86,10 +86,10 @@ class FileLayer(interfaces.layers.DataLayerInterface):
self._write_warning = False
self._location = self.config["location"]
self._accessor = resources.ResourceAccessor()
self._file_ = None # type: Optional[IO[Any]]
self._size = None # type: Optional[int]
self._file_: Optional[IO[Any]] = None
self._size: Optional[int] = None
# Construct the lock now (shared if made before threading) in case we ever need it
self._lock = DummyLock() # type: Union[DummyLock, threading.Lock]
self._lock: Union[DummyLock, threading.Lock] = DummyLock()
if constants.PARALLELISM == constants.Parallelism.Threading:
self._lock = threading.Lock()
# Instantiate the file to throw exceptions if the file doesn't open
+1 -1
View File
@@ -40,7 +40,7 @@ class QemuSuspendLayer(segmented.NonLinearlySegmentedLayer):
metadata: Optional[Dict[str, Any]] = None) -> None:
self._qemu_table_name = intermed.IntermediateSymbolTable.create(context, config_path, 'generic', 'qemu')
self._configuration = None
self._compressed = set() # type: Set[int]
self._compressed: Set[int] = set()
self._current_segment_name = b''
super().__init__(context = context, config_path = config_path, name = name, metadata = metadata)
+1 -1
View File
@@ -141,7 +141,7 @@ class RegistryHive(linear.LinearlyMappedLayer):
if key.endswith("\\"):
key = key[:-1]
key_array = key.split('\\')
found_key = [] # type: List[str]
found_key: List[str] = []
while key_array and node_key:
subkeys = node_key[-1].get_subkeys()
for subkey in subkeys:
@@ -48,7 +48,7 @@ class MultiStringScanner(layers.ScannerInterface):
def __init__(self, patterns: List[bytes]) -> None:
super().__init__()
self._pattern_trie = {} # type: Optional[Dict[int, Optional[Dict]]]
self._pattern_trie: Optional[Dict[int, Optional[Dict]]] = {}
for pattern in patterns:
self._process_pattern(pattern)
self._regex = self._process_trie(self._pattern_trie)
@@ -10,7 +10,7 @@ class MultiRegexp(object):
"""Algorithm for multi-string matching."""
def __init__(self) -> None:
self._pattern_strings = [] # type: List[bytes]
self._pattern_strings: List[bytes] = []
self._regex = re.compile(b'')
def add_pattern(self, pattern: bytes) -> None:
+3 -3
View File
@@ -25,9 +25,9 @@ class NonLinearlySegmentedLayer(interfaces.layers.TranslationLayerInterface, met
super().__init__(context = context, config_path = config_path, name = name, metadata = metadata)
self._base_layer = self.config["base_layer"]
self._segments = [] # type: List[Tuple[int, int, int, int]]
self._minaddr = None # type: Optional[int]
self._maxaddr = None # type: Optional[int]
self._segments: List[Tuple[int, int, int, int]] = []
self._minaddr: Optional[int] = None
self._maxaddr: Optional[int] = None
self._load_segments()
+9 -9
View File
@@ -95,7 +95,7 @@ class Function(interfaces.objects.ObjectInterface):
class PrimitiveObject(interfaces.objects.ObjectInterface):
"""PrimitiveObject is an interface for any objects that should simulate a
Python primitive."""
_struct_type = int # type: ClassVar[Type]
_struct_type: ClassVar[Type] = int
def __init__(self, context: interfaces.context.ContextInterface, type_name: str,
object_info: interfaces.objects.ObjectInformation, data_format: DataFormatInfo) -> None:
@@ -164,7 +164,7 @@ class PrimitiveObject(interfaces.objects.ObjectInterface):
# https://mail.python.org/pipermail/python-dev/2004-February/042537.html
class Boolean(PrimitiveObject, int):
"""Primitive Object that handles boolean types."""
_struct_type = int # type: ClassVar[Type]
_struct_type: ClassVar[Type] = int
class Integer(PrimitiveObject, int):
@@ -173,17 +173,17 @@ class Integer(PrimitiveObject, int):
class Float(PrimitiveObject, float):
"""Primitive Object that handles double or floating point numbers."""
_struct_type = float # type: ClassVar[Type]
_struct_type: ClassVar[Type] = float
class Char(PrimitiveObject, int):
"""Primitive Object that handles characters."""
_struct_type = int # type: ClassVar[Type]
_struct_type: ClassVar[Type] = int
class Bytes(PrimitiveObject, bytes):
"""Primitive Object that handles specific series of bytes."""
_struct_type = bytes # type: ClassVar[Type]
_struct_type: ClassVar[Type] = bytes
def __init__(self,
context: interfaces.context.ContextInterface,
@@ -227,7 +227,7 @@ class String(PrimitiveObject, str):
max_length: specifies the maximum possible length that the string could hold within memory
(for multibyte characters, this will not be the maximum length of the string)
"""
_struct_type = str # type: ClassVar[Type]
_struct_type: ClassVar[Type] = str
def __init__(self,
context: interfaces.context.ContextInterface,
@@ -453,7 +453,7 @@ class Enumeration(interfaces.objects.ObjectInterface, int):
@classmethod
def _generate_inverse_choices(cls, choices: Dict[str, int]) -> Dict[int, str]:
"""Generates the inverse choices for the object."""
inverse_choices = {} # type: Dict[int, str]
inverse_choices: Dict[int, str] = {}
for k, v in choices.items():
if v in inverse_choices:
# Technically this shouldn't be a problem, but since we inverse cache
@@ -601,7 +601,7 @@ class Array(interfaces.objects.ObjectInterface, collections.abc.Sequence):
def __getitem__(self, i):
"""Returns the i-th item from the array."""
result = [] # type: List[interfaces.objects.Template]
result: List[interfaces.objects.Template] = []
mask = self._context.layers[self.vol.layer_name].address_mask
# We use the range function to deal with slices for us
series = range(self.vol.count)[i]
@@ -649,7 +649,7 @@ class AggregateType(interfaces.objects.ObjectInterface):
size = size,
members = members)
# self._check_members(members)
self._concrete_members = {} # type: Dict[str, Dict]
self._concrete_members: Dict[str, Dict] = {}
def has_member(self, member_name: str) -> bool:
"""Returns whether the object would contain a member called
+5 -5
View File
@@ -65,7 +65,7 @@ class ObjectTemplate(interfaces.objects.Template):
Returns: an object adhereing to the :class:`~volatility3.framework.interfaces.objects.ObjectInterface`
"""
arguments = {} # type: Dict[str, Any]
arguments: Dict[str, Any] = {}
for arg in self.vol:
if arg != 'object_class':
arguments[arg] = self.vol[arg]
@@ -96,10 +96,10 @@ class ReferenceTemplate(interfaces.objects.Template):
symbol_name, table_name,
f"Template contains no information about its structure: {self.vol.type_name}")
size = property(_unresolved) # type: ClassVar[Any]
replace_child = _unresolved # type: ClassVar[Any]
relative_child_offset = _unresolved # type: ClassVar[Any]
has_member = _unresolved # type: ClassVar[Any]
size: ClassVar[Any] = property(_unresolved)
replace_child: ClassVar[Any] = _unresolved
relative_child_offset: ClassVar[Any] = _unresolved
has_member: ClassVar[Any] = _unresolved
def __call__(self, context: interfaces.context.ContextInterface, object_info: interfaces.objects.ObjectInformation):
template = context.symbol_space.get_type(self.vol.type_name)
+1 -1
View File
@@ -57,7 +57,7 @@ class Lsmod(plugins.PluginInterface):
except exceptions.InvalidAddressException:
return []
seen = set() # type: Set
seen: Set = set()
while kmod != 0 and \
kmod not in seen and \
+1 -1
View File
@@ -52,7 +52,7 @@ class Psaux(plugins.PluginInterface):
task_name = utility.array_to_string(task.p_comm)
args = [] # type: List[bytes]
args: List[bytes] = []
while argc > 0:
try:
+2 -2
View File
@@ -124,7 +124,7 @@ class PsList(interfaces.plugins.PluginInterface):
proc = kernel.object_from_symbol(symbol_name = "allproc").lh_first
seen = {} # type: Dict[int, int]
seen: Dict[int, int] = {}
while proc is not None and proc.vol.offset != 0:
if proc.vol.offset in seen:
vollog.log(logging.INFO, "Recursive process list detected (a result of non-atomic acquisition).")
@@ -165,7 +165,7 @@ class PsList(interfaces.plugins.PluginInterface):
queue_entry = kernel.object_from_symbol(symbol_name = "tasks")
seen = {} # type: Dict[int, int]
seen: Dict[int, int] = {}
for task in queue_entry.walk_list(queue_entry, "tasks", "task"):
if task.vol.offset in seen:
vollog.log(logging.INFO, "Recursive process list detected (a result of non-atomic acquisition).")
+1 -1
View File
@@ -48,7 +48,7 @@ class Timeliner(interfaces.plugins.PluginInterface):
super().__init__(*args, **kwargs)
self.timeline = {}
self.usable_plugins = None
self.automagics = None # type: Optional[List[interfaces.automagic.AutomagicInterface]]
self.automagics: Optional[List[interfaces.automagic.AutomagicInterface]] = None
@classmethod
def get_usable_plugins(cls, selected_list: List[str] = None) -> List[Type]:
@@ -191,9 +191,9 @@ class Callbacks(interfaces.plugins.PluginInterface):
continue
try:
component = ntkrnlmp.object(
component: Union[interfaces.renderers.BaseAbsentValue, interfaces.objects.ObjectInterface] = ntkrnlmp.object(
"string", absolute = True, offset = callback.Component, max_length = 64, errors = "replace"
) # type: Union[interfaces.renderers.BaseAbsentValue, interfaces.objects.ObjectInterface]
)
except exceptions.InvalidAddressException:
component = renderers.UnreadableValue()
@@ -172,7 +172,7 @@ class Handles(interfaces.plugins.PluginInterface):
A mapping of type indicies to type names
"""
type_map = {} # type: Dict[int, str]
type_map: Dict[int, str] = {}
kvo = context.layers[layer_name].config['kernel_virtual_offset']
ntkrnlmp = context.module(symbol_table, layer_name = layer_name, offset = kvo)
@@ -81,7 +81,7 @@ class ModScan(interfaces.plugins.PluginInterface):
Returns:
A list of session layer names
"""
seen_ids = [] # type: List[interfaces.objects.ObjectInterface]
seen_ids: List[interfaces.objects.ObjectInterface] = []
filter_func = pslist.PsList.create_pid_filter(pids or [])
for proc in pslist.PsList.list_processes(context = context,
@@ -86,7 +86,7 @@ class Modules(interfaces.plugins.PluginInterface):
Returns:
A list of session layer names
"""
seen_ids = [] # type: List[interfaces.objects.ObjectInterface]
seen_ids: List[interfaces.objects.ObjectInterface] = []
filter_func = pslist.PsList.create_pid_filter(pids or [])
for proc in pslist.PsList.list_processes(context = context,
@@ -338,7 +338,7 @@ class PoolScanner(plugins.PluginInterface):
An Iterable of pool constraints and the pool headers associated with them
"""
# Setup the pattern
constraint_lookup = {} # type: Dict[bytes, PoolConstraint]
constraint_lookup: Dict[bytes, PoolConstraint] = {}
for constraint in pool_constraints:
if constraint.tag in constraint_lookup:
raise ValueError(f"Constraint tag is used for more than one constraint: {repr(constraint.tag)}")
@@ -18,9 +18,9 @@ class PsTree(interfaces.plugins.PluginInterface):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self._processes = {} # type: Dict[int, interfaces.objects.ObjectInterface]
self._levels = {} # type: Dict[int, int]
self._children = {} # type: Dict[int, Set[int]]
self._processes: Dict[int, interfaces.objects.ObjectInterface] = {}
self._levels: Dict[int, int] = {}
self._children: Dict[int, Set[int]] = {}
@classmethod
def get_requirements(cls):
@@ -130,7 +130,7 @@ class PrintKey(interfaces.plugins.PluginInterface):
if isinstance(value_type, renderers.UnreadableValue):
vollog.debug("Couldn't read registry value type, so data is unreadable")
value_data = renderers.UnreadableValue() # type: Union[interfaces.renderers.BaseAbsentValue, bytes]
value_data: Union[interfaces.renderers.BaseAbsentValue, bytes] = renderers.UnreadableValue()
else:
try:
value_data = node.decode_data()
@@ -151,12 +151,12 @@ class UserAssist(interfaces.plugins.PluginInterface):
countkey_last_write_time = conversion.wintime_to_datetime(countkey.LastWriteTime.QuadPart)
# output the parent Count key
result = (
result: Tuple[int, Tuple[format_hints.Hex, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any]] = (
0, (renderers.format_hints.Hex(hive.hive_offset), hive_name, countkey_path,
countkey_last_write_time, "Key", renderers.NotApplicableValue(), renderers.NotApplicableValue(),
renderers.NotApplicableValue(), renderers.NotApplicableValue(), renderers.NotApplicableValue(),
renderers.NotApplicableValue(), renderers.NotApplicableValue())
) # type: Tuple[int, Tuple[format_hints.Hex, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any]]
)
yield result
# output any subkeys under Count
@@ -40,17 +40,18 @@ class Strings(interfaces.plugins.PluginInterface):
def run(self):
return renderers.TreeGrid([("String", str), ("Physical Address", format_hints.Hex), ("Result", str)],
self._generator())
self._generator)
@property
def _generator(self) -> Generator[Tuple, None, None]:
"""Generates results from a strings file."""
string_list = [] # type: List[Tuple[int,bytes]]
string_list: List[Tuple[int,bytes]] = []
# Test strings file format is accurate
accessor = resources.ResourceAccessor()
strings_fp = accessor.open(self.config['strings_file'], "rb")
line = strings_fp.readline()
count = 0 # type: float
count: float = 0
while line:
count += 1
try:
@@ -66,7 +67,8 @@ class Strings(interfaces.plugins.PluginInterface):
progress_callback = self._progress_callback,
pid_list = self.config['pid'])
last_prog = line_count = 0 # type: float
last_prog: float = 0
line_count: float = 0
num_strings = len(string_list)
for offset, string in string_list:
line_count += 1
@@ -119,7 +121,7 @@ class Strings(interfaces.plugins.PluginInterface):
filter = pslist.PsList.create_pid_filter(pid_list)
layer = context.layers[layer_name]
reverse_map = dict() # type: Dict[int, Set[Tuple[str, int]]]
reverse_map: Dict[int, Set[Tuple[str, int]]] = dict()
if isinstance(layer, intel.Intel):
# We don't care about errors, we just wanted chunks that map correctly
for mapval in layer.mapping(0x0, layer.maximum_address, ignore_errors = True):
@@ -41,7 +41,7 @@ class VirtMap(interfaces.plugins.PluginInterface):
if not isinstance(layer, intel.Intel):
raise
result = {} # type: Dict[str, List[Tuple[int, int]]]
result: Dict[str, List[Tuple[int, int]]] = {}
system_va_type = module.get_enumeration('_MI_SYSTEM_VA_TYPE')
large_page_size = (layer.page_size ** 2) // module.get_type("_MMPTE").size
@@ -84,7 +84,7 @@ class VirtMap(interfaces.plugins.PluginInterface):
def _enumerate_system_va_type(cls, large_page_size: int, system_range_start: int,
module: interfaces.context.ModuleInterface,
type_array: interfaces.objects.ObjectInterface) -> Dict[str, List[Tuple[int, int]]]:
result = {} # type: Dict[str, List[Tuple[int, int]]]
result: Dict[str, List[Tuple[int, int]]] = {}
system_va_type = module.get_enumeration('_MI_SYSTEM_VA_TYPE')
start = system_range_start
prev_entry = -1
+3 -3
View File
@@ -158,8 +158,8 @@ class TreeGrid(interfaces.renderers.TreeGrid):
"""
self._populated = False
self._row_count = 0
self._children = [] # type: List[interfaces.renderers.TreeNode]
converted_columns = [] # type: List[interfaces.renderers.Column]
self._children: List[interfaces.renderers.TreeNode] = []
converted_columns: List[interfaces.renderers.Column] = []
if len(columns) < 1:
raise ValueError("Columns must be a list containing at least one column")
for (name, column_type) in columns:
@@ -207,7 +207,7 @@ class TreeGrid(interfaces.renderers.TreeGrid):
if not self.populated:
try:
prev_nodes = [] # type: List[interfaces.renderers.TreeNode]
prev_nodes: List[interfaces.renderers.TreeNode] = []
for (level, item) in self._generator:
parent_index = min(len(prev_nodes), level)
parent = prev_nodes[parent_index - 1] if parent_index > 0 else None
@@ -24,7 +24,7 @@ def wintime_to_datetime(wintime: int) -> Union[interfaces.renderers.BaseAbsentVa
def unixtime_to_datetime(unixtime: int) -> Union[interfaces.renderers.BaseAbsentValue, datetime.datetime]:
ret = renderers.UnparsableValue() # type: Union[interfaces.renderers.BaseAbsentValue, datetime.datetime]
ret: Union[interfaces.renderers.BaseAbsentValue, datetime.datetime] = renderers.UnparsableValue()
if unixtime > 0:
try:
@@ -46,7 +46,7 @@ class MultiTypeData(bytes):
encoding: str = 'utf-16-le',
split_nulls: bool = False,
show_hex: bool = False) -> None:
self.converted_int = False # type: bool
self.converted_int: bool = False
if isinstance(original, int):
self.converted_int = True
self.encoding = encoding
+4 -4
View File
@@ -31,15 +31,15 @@ class SymbolSpace(interfaces.symbols.SymbolSpaceInterface):
def __init__(self) -> None:
super().__init__()
self._dict = collections.OrderedDict() # type: Dict[str, interfaces.symbols.BaseSymbolTableInterface]
self._dict: Dict[str, interfaces.symbols.BaseSymbolTableInterface] = collections.OrderedDict()
# Permanently cache all resolved symbols
self._resolved = {} # type: Dict[str, interfaces.objects.Template]
self._resolved_symbols = {} # type: Dict[str, interfaces.objects.Template]
self._resolved: Dict[str, interfaces.objects.Template] = {}
self._resolved_symbols: Dict[str, interfaces.objects.Template] = {}
def clear_symbol_cache(self, table_name: str = None) -> None:
"""Clears the symbol cache for the specified table name. If no table
name is specified, the caches of all symbol tables are cleared."""
table_list = list() # type: List[interfaces.symbols.BaseSymbolTableInterface]
table_list: List[interfaces.symbols.BaseSymbolTableInterface] = list()
if table_name is None:
table_list = list(self._dict.values())
else:
+2 -2
View File
@@ -282,8 +282,8 @@ class ISFormatTable(interfaces.symbols.SymbolTableInterface, metaclass = ABCMeta
raise TypeError("Native table not provided")
nt.name = name + "_natives"
super().__init__(context, config_path, name, nt, table_mapping = table_mapping)
self._overrides = {} # type: Dict[str, Type[interfaces.objects.ObjectInterface]]
self._symbol_cache = {} # type: Dict[str, interfaces.symbols.SymbolInterface]
self._overrides: Dict[str, Type[interfaces.objects.ObjectInterface]] = {}
self._symbol_cache: Dict[str, interfaces.symbols.SymbolInterface] = {}
def _get_natives(self) -> Optional[interfaces.symbols.NativeTableInterface]:
"""Determines the appropriate native_types to use from the JSON
@@ -46,7 +46,7 @@ class LinuxUtilities(interfaces.configuration.VersionableInterface):
@classmethod
def _do_get_path(cls, rdentry, rmnt, dentry, vfsmnt) -> str:
ret_path = [] # type: List[str]
ret_path: List[str] = []
while dentry != rdentry or vfsmnt != rmnt:
dname = dentry.path()
@@ -160,7 +160,7 @@ class MacUtilities(interfaces.configuration.VersionableInterface):
list_next_member: str,
next_member: str,
max_elements: int = 4096) -> Iterable[interfaces.objects.ObjectInterface]:
seen = set() # type: Set[int]
seen: Set[int] = set()
try:
current = queue.member(attr = list_head_member)
@@ -48,7 +48,7 @@ class proc(generic.GenericIntelProcess):
except exceptions.InvalidAddressException:
return
seen = set() # type: Set[int]
seen: Set[int] = set()
for i in range(task.map.hdr.nentries):
if not current_map or current_map.vol.offset in seen:
+3 -3
View File
@@ -15,7 +15,7 @@ class NativeTable(interfaces.symbols.NativeTableInterface):
def __init__(self, name: str, native_dictionary: Dict[str, Any]) -> None:
super().__init__(name, self)
self._native_dictionary = copy.deepcopy(native_dictionary)
self._overrides = {} # type: Dict[str, interfaces.objects.ObjectInterface]
self._overrides: Dict[str, interfaces.objects.ObjectInterface] = {}
for native_type in self._native_dictionary:
native_class, _native_struct = self._native_dictionary[native_type]
self._overrides[native_type] = native_class
@@ -49,8 +49,8 @@ class NativeTable(interfaces.symbols.NativeTableInterface):
table_name, type_name = name_split
prefix = table_name + constants.BANG
additional = {} # type: Dict[str, Any]
obj = None # type: Optional[Type[interfaces.objects.ObjectInterface]]
additional: Dict[str, Any] = {}
obj: Optional[Type[interfaces.objects.ObjectInterface]] = None
if type_name == 'void' or type_name == 'function':
obj = objects.Void
elif type_name == 'array':
@@ -388,7 +388,7 @@ class FILE_OBJECT(objects.StructType, pool.ExecutiveObject):
self.FileName.Buffer)
def file_name_with_device(self) -> Union[str, interfaces.renderers.BaseAbsentValue]:
name = renderers.UnreadableValue() # type: Union[str, interfaces.renderers.BaseAbsentValue]
name: Union[str, interfaces.renderers.BaseAbsentValue] = renderers.UnreadableValue()
# this pointer needs to be checked against native_layer_name because the object may
# be instantiated from a primary (virtual) layer or a memory (physical) layer.
@@ -214,7 +214,7 @@ class POOL_HEADER_VISTA(POOL_HEADER):
class POOL_TRACKER_BIG_PAGES(objects.StructType):
"""A kernel big page pool tracker."""
pool_type_lookup = {} # type: Dict[str, str]
pool_type_lookup: Dict[str, str] = {}
def _generate_pool_type_lookup(self):
# Enumeration._generate_inverse_choices() raises ValueError because multiple enum names map to the same
@@ -265,18 +265,18 @@ class PdbReader:
database_name: Optional[str] = None,
progress_callback: constants.ProgressCallback = None) -> None:
self._layer_name, self._context = self.load_pdb_layer(context, location)
self._dbiheader = None # type: Optional[interfaces.objects.ObjectInterface]
self._dbiheader: Optional[interfaces.objects.ObjectInterface] = None
if not progress_callback:
progress_callback = lambda x, y: None
self._progress_callback = progress_callback
self.types = [
] # type: List[Tuple[interfaces.objects.ObjectInterface, Optional[str], interfaces.objects.ObjectInterface]]
self.bases = {} # type: Dict[str, Any]
self.user_types = {} # type: Dict[str, Any]
self.enumerations = {} # type: Dict[str, Any]
self.symbols = {} # type: Dict[str, Any]
self._omap_mapping = [] # type: List[Tuple[int, int]]
self._sections = [] # type: List[interfaces.objects.ObjectInterface]
self.types: List[Tuple[interfaces.objects.ObjectInterface, Optional[str], interfaces.objects.ObjectInterface]] = [
]
self.bases: Dict[str, Any] = {}
self.user_types: Dict[str, Any] = {}
self.enumerations: Dict[str, Any] = {}
self.symbols: Dict[str, Any] = {}
self._omap_mapping: List[Tuple[int, int]] = []
self._sections: List[interfaces.objects.ObjectInterface] = []
self.metadata = {"format": "6.1.0", "windows": {}}
self._database_name = database_name
@@ -381,7 +381,7 @@ class PdbReader:
raise ValueError("Maximum {} index is smaller than minimum TPI index, found: {} < {} ".format(
stream_name, header.index_max, header.index_min))
# Reset the state
info_references = {} # type: Dict[str, int]
info_references: Dict[str, int] = {}
offset = header.header_size
# Ensure we use the same type everywhere
length_type = "unsigned short"
@@ -586,7 +586,7 @@ class PdbReader:
if index < 0x1000:
base_name, base = primatives[index & 0xff]
self.bases[base_name] = base
result = {"kind": "base", "name": base_name} # type: Union[List[Dict[str, Any]], Dict[str, Any]]
result: Union[List[Dict[str, Any]], Dict[str, Any]] = {"kind": "base", "name": base_name}
indirection = (index & 0xf00)
if indirection:
pointer_name, pointer_base = indirections[indirection]
@@ -639,7 +639,7 @@ class PdbReader:
"""Returns the size of the structure based on the type index
provided."""
result = -1
name = '' # type: Optional[str]
name: Optional[str] = ''
if index < 0x1000:
if (index & 0xf00):
_, base = indirections[index & 0xf00]
@@ -837,7 +837,7 @@ class PdbReader:
def convert_fields(self, fields: int) -> Dict[Optional[str], Dict[str, Any]]:
"""Converts a field list into a list of fields."""
result = {} # type: Dict[Optional[str], Dict[str, Any]]
result: Dict[Optional[str], Dict[str, Any]] = {}
_, _, fields_struct = self.types[fields]
if not isinstance(fields_struct, list):
vollog.warning("Fields structure did not contain a list of fields")
+1 -1
View File
@@ -18,7 +18,7 @@ cached_validation_filepath = os.path.join(constants.CACHE_PATH, "valid_isf.hashc
def load_cached_validations() -> Set[str]:
"""Loads up the list of successfully cached json objects, so we don't need
to revalidate them."""
validhashes = set() # type: Set
validhashes: Set = set()
if os.path.exists(cached_validation_filepath):
with open(cached_validation_filepath, "r") as f:
validhashes.update(json.load(f))