Improve ListRequirement handling (default values, etc).

This commit is contained in:
Mike Auty
2018-02-11 02:16:53 +00:00
parent b7c8961d50
commit e8212df604
3 changed files with 21 additions and 15 deletions
+6 -9
View File
@@ -135,6 +135,10 @@ class CommandLine(object):
for requirement in configurables_list[configurable].get_requirements():
value = vargs.get(requirement.name, None)
if value is not None:
if isinstance(requirement, requirements.ListRequirement):
if not isinstance(value, list):
raise TypeError("Configuration for ListRequirement was not a list")
value = [requirement.element_type(x) for x in value]
if not inspect.isclass(configurables_list[configurable]):
config_path = configurables_list[configurable].config_path
else:
@@ -228,15 +232,8 @@ class CommandLine(object):
if "type" in additional:
del additional["type"]
elif isinstance(requirement, volatility.framework.configuration.requirements.ListRequirement):
if requirement.min_elements != requirement.max_elements:
if requirement.min_elements > 0:
additional["nargs"] = "+"
additional["nargs"] = "*"
# We can't test for min_elements > 1 or going over max_elements but rather than warning here,
# we expect the plugin to fail validation instead
else:
additional["nargs"] = requirement.max_elements
additional["type"] = requirement.element_type
# This is a trick to generate a list of values
additional["type"] = lambda x: x.split(',')
elif isinstance(requirement, volatility.framework.configuration.requirements.ChoiceRequirement):
additional["type"] = str
additional["choices"] = requirement.choices
@@ -81,9 +81,15 @@ class ListRequirement(interfaces_configuration.RequirementInterface):
def unsatisfied(self, context: interfaces.context.ContextInterface, config_path: str) -> typing.List[str]:
"""Check the types on each of the returned values and their number and then call the element type's check for each one"""
value = self.config_value(context, config_path)
if value is None:
raise ValueError("No value stored in the configuration")
default = None
value = self.config_value(context, config_path, default)
if not value and self.min_elements > 0:
vollog.log(constants.LOGLEVEL_V, "ListRequirement Unsatisfied - ListRequirement has non-zero min_elements")
return [interfaces_configuration.path_join(config_path, self.name)]
if value == default:
# We need to differentiate between no value and an empty list
vollog.log(constants.LOGLEVEL_V, "ListRequirement Unsatisfied - Value was not specified")
return [interfaces_configuration.path_join(config_path, self.name)]
if not isinstance(value, list):
# TODO: Check this is the correct response for an error
raise ValueError("Unexpected config value found: {}".format(repr(value)))
@@ -94,7 +100,8 @@ class ListRequirement(interfaces_configuration.RequirementInterface):
vollog.log(constants.LOGLEVEL_V, "TypeError - Too many values provided to list option.")
return [interfaces_configuration.path_join(config_path, self.name)]
if not all([self._check_type(element, self.element_type) for element in value]):
vollog.log(constants.LOGLEVEL_V, "TypeError - At least one element in the list is not of the correct type.")
vollog.log(constants.LOGLEVEL_V,
"TypeError - At least one element in the list is not of the correct type.")
return [interfaces_configuration.path_join(config_path, self.name)]
return []
+4 -2
View File
@@ -69,14 +69,16 @@ class AutomagicInterface(interfaces_configuration.ConfigurableInterface, metacla
:param context: Context on which to operate
:param config_path: Configuration path of the top-level requirement
:param requirement: Top-level requirement whose subrequirements will all be searched
:param requirement_root: Top-level requirement whose subrequirements will all be searched
:param requirement_type: Type of requirement to find
:param shortcut: Only returns requirements that live under unsatisfied requirements
:return: A list of tuples containing the config_path, sub_config_path and requirement identifying the SymbolRequirements
"""
sub_config_path = interfaces_configuration.path_join(config_path, requirement_root.name)
results = []
recurse = not shortcut
if isinstance(requirement_root, requirement_type):
if not shortcut or requirement_root.unsatisfied(context, config_path):
if recurse or requirement_root.unsatisfied(context, config_path):
results.append((config_path, sub_config_path, requirement_root))
else:
recurse = True