diff --git a/capa/features/common.py b/capa/features/common.py index 5be8ffca..f431336a 100644 --- a/capa/features/common.py +++ b/capa/features/common.py @@ -105,6 +105,25 @@ class Result: def __nonzero__(self): return self.success + def __str__(self): + # as this object isn't user facing, this formatting is just to help with debugging + + lines = [] + def rec(m: "Result", indent: int): + if isinstance(m.statement, capa.engine.Statement): + line = (" " * indent) + str(m.statement.name) + " " + str(m.success) + else: + line = (" " * indent) + str(m.statement) + " " + str(m.success) + " " + str(m.locations) + + lines.append(line) + + for child in m.children: + rec(child, indent + 1) + + rec(self, 0) + return "\n".join(lines) + + class Feature(abc.ABC): # noqa: B024 # this is an abstract class, since we don't want anyone to instantiate it directly, diff --git a/capa/render/result_document.py b/capa/render/result_document.py index 9ef529be..ce3677ee 100644 --- a/capa/render/result_document.py +++ b/capa/render/result_document.py @@ -474,6 +474,26 @@ class Match(FrozenModel): children=children, ) + def __str__(self): + # as this object isn't user facing, this formatting is just to help with debugging + + lines = [] + def rec(m: "Match", indent: int): + if isinstance(m.node, StatementNode): + line = (" " * indent) + str(m.node.statement.type) + " " + str(m.success) + elif isinstance(m.node, FeatureNode): + line = (" " * indent) + str(m.node.feature) + " " + str(m.success) + " " + str(m.locations) + else: + raise ValueError("unexpected node type") + + lines.append(line) + + for child in m.children: + rec(child, indent + 1) + + rec(self, 0) + return "\n".join(lines) + def parse_parts_id(s: str): id_ = ""