diff options
| author | blasty <peter@haxx.in> | 2026-09-25 14:59:48 +0200 |
|---|---|---|
| committer | blasty <peter@haxx.in> | 2026-09-25 14:59:48 +0200 |
| commit | 15425df0a6e09984fdab3f86354620d4d8656806 (patch) | |
| tree | cf92f86fd343cbfc04f19be895a337b304c576ec /tests/test_launch.py | |
| parent | Merge PR #2 from mrexodia: fix pseudocode/listing tag parsing, ida-nexus 0.13.0 (diff) | |
| download | ida-tui-15425df0a6e09984fdab3f86354620d4d8656806.tar.gz ida-tui-15425df0a6e09984fdab3f86354620d4d8656806.tar.xz ida-tui-15425df0a6e09984fdab3f86354620d4d8656806.zip | |
Offer a writable database location instead of failing the open
`ida-tui /bin/ls` asked IDA to create /bin/ls.i64, which a normal user
cannot write, and what came back was the backend's account of it:
idalib worker launcher 2425195 exited with status 1
[ida-nexus] Failed to open database /usr/bin/ls
after a full analysis wait, naming neither the file it could not create
nor the reason. Nothing in the message points at permissions, and there
was no way forward from it.
idatui/idbpath.py answers the question before anything is opened: where
would the database go (mirroring ida_nexus's own derivation), can it go
there (os.access only — the pre-flight check must not create files), and
where instead. The proposal is stable per binary
(~/.local/share/idatui/db/<name>-<sha1(realpath)[:8]>.i64) so reopening
the same binary resumes the same names and comments, and hashed so two
busyboxes from different directories cannot collide. DATA_HOME rather
than CACHE_HOME on purpose: an .i64 holds the whole session, and cache
directories are something cleaners may empty.
The answer becomes NexusClient(output_database=...) — the option project
mode already uses to keep everything in its sidecar. `--idb PATH` (also
forwarded by `pane spawn`) says where without being asked. An RPC-driven
TUI is never asked: `pane spawn` polls for ready and would sit out its
whole timeout in front of a modal nobody can answer, so it relocates and
says so in the status line. A failed open re-offers relocation after a
real create probe, since os.access does not know about ACLs, a lying
network mount or a full disk.
tests/test_idbpath.py (pure, 32 checks) pins the path arithmetic, the two
properties of the proposal and that neither check touches the user's
directory; tests/test_idb_relocate_ui.py (textual, no worker, 24 checks)
drives the dialog, Esc, an edited path, the untouched common case, --idb,
the RPC path, and that output_database actually reaches the client.
Verified end to end against a real /bin/ls: 400 functions, and a rename
saved in one session comes back in the next.
Diffstat (limited to 'tests/test_launch.py')
| -rw-r--r-- | tests/test_launch.py | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/tests/test_launch.py b/tests/test_launch.py index 5c05d08..5d90006 100644 --- a/tests/test_launch.py +++ b/tests/test_launch.py @@ -83,8 +83,29 @@ def t_load_args(): check("extra ida_args are passed through", "-p1" in c, c) +def t_idb_option(): + """``--idb`` names where the database goes, for a binary in /bin. + + The launcher only has to accept it and hand it over; choosing a location and + asking about one live in idbpath/app (tests/test_idbpath.py). + """ + src = open(launch.__file__, encoding="utf-8").read() + check("the launcher offers --idb", '"--idb"' in src) + check("...and passes it to the app", "idb_path=idb_path" in src) + with tempfile.TemporaryDirectory() as tmp: + # A project keeps its databases in its sidecar, so the two options mean + # contradictory things; refusing beats silently ignoring one. + proj = os.path.join(tmp, "p.idatui-project") + binary = os.path.join(tmp, "bin") + touch(binary) + rc = launch.main( + ["--project", proj, binary, "--idb", os.path.join(tmp, "x.i64")] + ) + check("--idb with --project is refused", rc == 2, f"rc={rc}") + + def main() -> int: - for fn in (t_no_lock_sweeping, t_load_args): + for fn in (t_no_lock_sweeping, t_load_args, t_idb_option): print(f"\n{fn.__name__}") try: fn() |
