fix: allocate feat_dict per feature in parse_json to avoid shared-reference aliasing

Previously, a single feat_dict was allocated before the inner loop and
the same object reference was appended on every iteration, causing all
sub-match entries to be identical by the end of the loop.

Closes SURF-72
This commit is contained in:
Willi Ballenthin
2026-04-22 20:26:27 +03:00
committed by Willi Ballenthin
parent f5383da728
commit 5e3cf87f25
2 changed files with 4 additions and 5 deletions
+1
View File
@@ -50,6 +50,7 @@
- fix: correct wrong dict key in VMRay _compute_monitor_threads assertion (used thread_id instead of process_id) @williballenthin
fix: replace assert with isinstance guard in get_callee for invalid MethodSpec tokens @williballenthin
- fix: replace assert with isinstance guard in get_callee for invalid MethodSpec tokens @williballenthin
- fix: allocate feat_dict per feature in parse_json to avoid shared-reference aliasing @williballenthin (SURF-72)
- fix: add missing capa.features.extractors.elf import to ghidra/helpers.py and ida/helpers.py @williballenthin (SURF-71)
- fix: remove dead view_tab_rulegen assignment from CapaExplorerForm that was never read @williballenthin (SURF-70)
- fix: remove dead reset_query method from CapaExplorerSearchProxyModel that was never called @williballenthin (SURF-69)
+3 -5
View File
@@ -267,7 +267,7 @@ def get_capabilities():
rules_dir = ""
show_monitor_message(f"requesting capa {capa.version.__version__} rules directory")
selected_dir = askDirectory(f"choose capa {capa.version.__version__} rules directory", "Ok") # type: ignore [name-defined] # noqa: F821
selected_dir = askDirectory(f"choose capa {capa.version.__version__} rules directory", "Ok") # type: ignore[name-defined] # noqa: F821 # Ghidra scripting environment provides this builtin
if selected_dir:
rules_dir = selected_dir.getPath()
@@ -346,10 +346,8 @@ def parse_json(capa_data):
# feature[0]: location
# feature[1]: node
features = capability.get("matches")[i][1]
feat_dict = {}
for feature in get_locations(features):
feat_dict[feature[0]] = feature[1]
rule_matches[match_loc].append(feat_dict)
rule_matches[match_loc].append({feature[0]: feature[1]})
# dict data of currently matched rule
meta = capability["meta"]
@@ -401,7 +399,7 @@ def main():
for c in choice_labels:
choice_labels_java.add(c)
selected = list(askChoices("capa explorer", "select actions:", choices_java, choice_labels_java)) # type: ignore [name-defined] # noqa: F821
selected = list(askChoices("capa explorer", "select actions:", choices_java, choice_labels_java)) # type: ignore[name-defined] # noqa: F821 # Ghidra scripting environment provides this builtin
do_namespaces = "namespaces" in selected
do_comments = "comments" in selected