Skip to content

Commit d238c59

Browse files
authored
Merge pull request volatilityfoundation#1254 from volatilityfoundation/issues/plugin-requirement-recursion
Core: Verify plugin requirements of plugins
2 parents 7d75c17 + 9152f33 commit d238c59

File tree

1 file changed

+40
-2
lines changed

1 file changed

+40
-2
lines changed

volatility3/framework/configuration/requirements.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,12 +527,14 @@ class VersionRequirement(interfaces.configuration.RequirementInterface):
527527
def __init__(
528528
self,
529529
name: str,
530-
description: str = None,
530+
description: Optional[str] = None,
531531
default: bool = False,
532532
optional: bool = False,
533533
component: Type[interfaces.configuration.VersionableInterface] = None,
534534
version: Optional[Tuple[int, ...]] = None,
535535
) -> None:
536+
if description is None:
537+
description = f"Version {'.'.join([str(x) for x in version])} dependency on {component.__module__}.{component.__name__} unmet"
536538
super().__init__(
537539
name=name, description=description, default=default, optional=optional
538540
)
@@ -544,15 +546,51 @@ def __init__(
544546
self._version = version
545547

546548
def unsatisfied(
547-
self, context: interfaces.context.ContextInterface, config_path: str
549+
self,
550+
context: interfaces.context.ContextInterface,
551+
config_path: str,
552+
accumulator: Optional[
553+
List[interfaces.configuration.VersionableInterface]
554+
] = None,
548555
) -> Dict[str, interfaces.configuration.RequirementInterface]:
549556
# Mypy doesn't appreciate our classproperty implementation, self._plugin.version has no type
550557
config_path = interfaces.configuration.path_join(config_path, self.name)
551558
if not self.matches_required(self._version, self._component.version):
552559
return {config_path: self}
560+
561+
recurse = True
562+
if accumulator is None:
563+
accumulator = set([self._component])
564+
else:
565+
if self._component in accumulator:
566+
recurse = False
567+
else:
568+
accumulator.add(self._component)
569+
570+
# Check for child requirements
571+
if (
572+
issubclass(self._component, interfaces.configuration.ConfigurableInterface)
573+
and recurse
574+
):
575+
result = {}
576+
for requirement in self._component.get_requirements():
577+
if not requirement.optional and isinstance(
578+
requirement, VersionRequirement
579+
):
580+
result.update(
581+
requirement.unsatisfied(
582+
context, config_path, accumulator.copy()
583+
)
584+
)
585+
586+
if result:
587+
result.update({config_path: self})
588+
return result
589+
553590
context.config[interfaces.configuration.path_join(config_path, self.name)] = (
554591
True
555592
)
593+
556594
return {}
557595

558596
@classmethod

0 commit comments

Comments
 (0)