Skip to content

Commit

Permalink
Fix self referencing Switch heads (angr#3861)
Browse files Browse the repository at this point in the history
* Fix self referencing Switch heads
  • Loading branch information
mahaloz authored Mar 15, 2023
1 parent b3ba6bc commit 7387188
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,13 @@ def _analyze(self, cache=None):
# update the block
self._update_block(original_head, new_head)

# sanity check that no switch head points to either itself
# or to any if-head that was merged into the new switch head; this
# would result in a successor node no longer being present in the graph
if any(onode not in graph_copy for onode in original_nodes):
self.out_graph = None
return

# add edges between the head and case nodes
for onode in original_nodes:
successors = list(graph_copy.successors(onode))
Expand Down
26 changes: 26 additions & 0 deletions tests/test_decompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2274,6 +2274,32 @@ def test_switch_case_shared_case_nodes_b2sum_digest(self, decompiler_options=Non

assert d.codegen.text.count("switch") == 1

@for_all_structuring_algos
def test_no_switch_case_touch_touch(self, decompiler_options=None):
# node 0x40015b is an if-node that is merged into a switch case node with other if-node's that
# have it as a successor, resulting in a switch that point's to its old heads; in this case,
# the switch should not exist at all AND not crash
bin_path = os.path.join(test_location, "x86_64", "decompiler", "touch_touch_no_switch.o")
proj = angr.Project(bin_path, auto_load_libs=False)

all_optimization_passes = angr.analyses.decompiler.optimization_passes.get_default_optimization_passes(
"AMD64", "linux"
)
all_optimization_passes = [
p
for p in all_optimization_passes
if p is not angr.analyses.decompiler.optimization_passes.EagerReturnsSimplifier
]

cfg = proj.analyses.CFGFast(normalize=True, data_references=True)
f = proj.kb.functions["touch"]
d = proj.analyses[Decompiler].prep()(
f, cfg=cfg.model, options=decompiler_options, optimization_passes=all_optimization_passes
)
self._print_decompilation_result(d)

assert d.codegen.text.count("switch") == 0


if __name__ == "__main__":
unittest.main()

0 comments on commit 7387188

Please sign in to comment.