aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-07-09 19:47:38 +0200
committerblasty <blasty@local>2026-07-09 19:47:38 +0200
commit737744644f0cc45d73e34731046db51326f3ffdd (patch)
tree5755fe79416af315c16b93502570a5c5fd1afe44 /tests
parentdocs: TEXTUAL_NOTES.md — Textual pitfalls, app patterns, testing gotchas (diff)
downloadida-tui-737744644f0cc45d73e34731046db51326f3ffdd.tar.gz
ida-tui-737744644f0cc45d73e34731046db51326f3ffdd.tar.xz
ida-tui-737744644f0cc45d73e34731046db51326f3ffdd.zip
fix: xref-select navigated to the wrong place (ordinary-flow contamination)
xrefs data doesn't distinguish a call/jump from ordinary flow (both type=code), so _xrefs_disasm's 'first code from-xref' subject picked the fall-through to the NEXT instruction on a plain line. Its only xref is the flow edge back, so selecting it jumped to the current function at line 0 instead of a real caller. Drop the from-xref subject entirely: use the symbol under the cursor if any, else the current address (xrefs-to a function entry == its callers). Now selecting an xref lands on the exact referencing function AND line. pilot suite 59/59.
Diffstat (limited to 'tests')
-rw-r--r--tests/test_tui.py35
1 files changed, 35 insertions, 0 deletions
diff --git a/tests/test_tui.py b/tests/test_tui.py
index f43c4a2..d14b525 100644
--- a/tests/test_tui.py
+++ b/tests/test_tui.py
@@ -303,6 +303,41 @@ async def run(db):
check("Esc closes the xrefs popup",
not isinstance(app.screen, XrefsScreen))
+ # Selecting an xref must land on the referencing SITE (right function
+ # AND line), not the function under the cursor.
+ xf = None
+ for cand in app.program.functions().all_loaded()[:600]:
+ codex = [x for x in app.program.xrefs_to(cand.addr)
+ if x.type == "code" and x.frm]
+ if codex:
+ xf = (cand, codex[0])
+ break
+ if xf is None:
+ check("found a function with a code xref", False)
+ else:
+ xfn, xref = xf
+ xexp = app.program.disasm(xref.fn_addr).index_of_ea(xref.frm)
+ await pilot.press("g")
+ await pilot.pause(0.2)
+ for ch in xfn.name:
+ await pilot.press(ch)
+ await pilot.press("enter")
+ await wait_until(pilot, lambda: dis.total > 0 and app._cur.ea == xfn.addr,
+ timeout=20)
+ dis.focus()
+ dis.cursor, dis.cursor_x = 0, 0 # on the entry (address column)
+ await pilot.press("x")
+ await wait_until(pilot, lambda: isinstance(app.screen, XrefsScreen), 25)
+ app.screen.query_one(OptionList).highlighted = 0
+ await pilot.press("enter")
+ await wait_until(pilot, lambda: not isinstance(app.screen, XrefsScreen), 25)
+ await wait_until(pilot, lambda: app._cur.ea == xref.fn_addr, timeout=25)
+ await pilot.pause(0.3)
+ check("xref-select lands on the referencing function + line",
+ app._cur.ea == xref.fn_addr and dis.cursor == xexp,
+ f"cur={app._cur.ea:#x} (want {xref.fn_addr:#x}) "
+ f"cursor={dis.cursor} (want {xexp})")
+
# Column cursor: h/l move it; following the symbol under the cursor.
dis.focus()
dis.cursor = call_idx