diff options
| author | idatui <user@clank> | 2026-08-09 14:17:13 +0200 |
|---|---|---|
| committer | idatui <user@clank> | 2026-08-09 14:17:13 +0200 |
| commit | d74b6f53e0969efc586d52776fa3b6d40b92a650 (patch) | |
| tree | 8baf17c3f8f0dfa57b07863e4cf8d376d4bd1788 /tests/_fixtures.py | |
| parent | Graph: fix the triskel fallbacks, and say why when it still falls back (diff) | |
| download | ida-tui-d74b6f53e0969efc586d52776fa3b6d40b92a650.tar.gz ida-tui-d74b6f53e0969efc586d52776fa3b6d40b92a650.tar.xz ida-tui-d74b6f53e0969efc586d52776fa3b6d40b92a650.zip | |
Graph: never hand triskel a block its root cannot reach
"EMPTY BL" in the status bar is triskel's own bracket-list assertion from
its SESE pass, and it turned out to be the mild version of the problem.
Triskel's graph root is whichever node was created FIRST, and every
analysis walks out from it. Anything unreachable from that node is
undefined behaviour. We were:
- creating nodes in id order, so the root was the lowest-numbered
block rather than the entry, and
- splitting only WEAKLY connected components, which says nothing about
reachability.
A 7-block CFG whose entry has no successors -- IDA hands those out for
thunks and for dead code it could not resolve -- SEGFAULTS the
interpreter. That is unsurvivable: it takes the session down and there
is no exception to fall back from.
Now the entry is created first, orphan blocks are attached to it with
phantom edges that steer placement but are never drawn (one edge usually
adopts a whole orphan subgraph, attached at a node no other orphan
reaches), and reachability is asserted in python BEFORE crossing into
C++. This replaces the component splitting entirely: one layout instead
of N stacked side by side, and triskel gets to place the orphans.
The reproducer is now a test (t_unreachable_entry). Remaining fallbacks
on the ls corpus are 8/1200 layouts, all the upstream box-overlap
defect, all but one on 300-500 block functions.
Diffstat (limited to 'tests/_fixtures.py')
0 files changed, 0 insertions, 0 deletions
