aboutsummaryrefslogtreecommitdiffstats
path: root/idatui/domain.py
diff options
context:
space:
mode:
authorblasty <peter@haxx.in>2026-07-11 10:59:48 +0200
committerblasty <peter@haxx.in>2026-07-11 10:59:48 +0200
commite769336aa753639f26208fd7755c1585d59caf41 (patch)
tree4be70a40c201206f4e6286742af5c6ca2ebb1c78 /idatui/domain.py
parentdrive pc: render pseudocode in the TUI, not just the driver (diff)
downloadida-tui-e769336aa753639f26208fd7755c1585d59caf41.tar.gz
ida-tui-e769336aa753639f26208fd7755c1585d59caf41.tar.xz
ida-tui-e769336aa753639f26208fd7755c1585d59caf41.zip
fix: don't hang drive pc on undecompilable functions
toggle_view's settle predicate (lambda: app._active != before) never fired when tabbing toward pseudocode on a function Hex-Rays can't decompile: App._apply_decomp snaps the view back to disasm, so _active returns to its prior value -> full 20s settle timeout (x2 in _show_decomp, ~40s for drive pc). Recognize the decomp-failed fallback as settled. Also harden two amplifiers surfaced by the same case: - rpcclient: the CLI socket had no read timeout and would block forever on any server slowness; add a bounded settimeout (IDATUI_RPC_TIMEOUT, default 90s) with a clear error. - domain.decompile: pass a bounded 15s timeout and cache failures, so a failing decompile can't sit at the 30s client default or be re-run by transport retries.
Diffstat (limited to 'idatui/domain.py')
-rw-r--r--idatui/domain.py17
1 files changed, 16 insertions, 1 deletions
diff --git a/idatui/domain.py b/idatui/domain.py
index 826d0f7..cc95b21 100644
--- a/idatui/domain.py
+++ b/idatui/domain.py
@@ -36,6 +36,7 @@ from .client import IDAClient, IDAToolError
LIST_PAGE = 500
DISASM_BLOCK = 256 # instructions per cached/fetched block (<= disasm cap)
HEX_BLOCK = 4096 # bytes per cached/fetched hex block
+DECOMPILE_TIMEOUT = 15.0 # s; cap per decompile so a failing one can't hang the CLI
_TRUNC_RE = re.compile(r"\[(\d+) chars total\]\s*$")
@@ -741,7 +742,21 @@ class Program:
self.client.call("force_recompile", items=[{"addr": hex(ea)}])
except Exception: # noqa: BLE001
pass
- envelope = self.client.call_envelope("decompile", addr=hex(ea))
+ # Bound the decompile: a function Hex-Rays can't handle tends to stall
+ # near the client's default 30s timeout, and the transport retries a
+ # dropped connection up to max_retries+1 times, re-running the failing
+ # decompile each time. Cap it so the worst case stays well under the
+ # rpcclient socket timeout, and cache the failure below so a re-request
+ # returns instantly instead of re-grinding.
+ try:
+ envelope = self.client.call_envelope(
+ "decompile", addr=hex(ea), timeout=DECOMPILE_TIMEOUT
+ )
+ except Exception as e: # noqa: BLE001 -- surface as a failed decompile
+ dec = Decompilation(ea, None, True, f"decompile error: {e}", False, None)
+ with self._lock:
+ self._decomp[ea] = (dec, self._name_gen)
+ return dec
result = envelope.get("result", {})
payload = result.get("structuredContent")
if payload is None: # fall back to text content