<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ida-tui.git/tests/test_search.py, branch main</title>
<subtitle>tui for headless ida</subtitle>
<id>https://git.sl0p.foo/ida-tui.git/atom/tests/test_search.py?h=main</id>
<link rel='self' href='https://git.sl0p.foo/ida-tui.git/atom/tests/test_search.py?h=main'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/'/>
<updated>2026-08-07T21:16:30Z</updated>
<entry>
<title>Ctrl+F: search the whole database, by text or by bytes</title>
<updated>2026-08-07T21:16:30Z</updated>
<author>
<name>blasty</name>
<email>blasty@local</email>
</author>
<published>2026-08-07T21:16:30Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=41b3710d5b6f9be24430fd55c46c83f9ae3b8d83'/>
<id>urn:sha1:41b3710d5b6f9be24430fd55c46c83f9ae3b8d83</id>
<content type='text'>
`/` only ever searched the lines of the view you were in. This adds the
search you actually need on a binary: over the entire database, either
through the rendered disassembly or through the image.

* **text** matches the line as displayed, whitespace-normalised, so
  `call cs:` finds `call    cs:getenv_ptr` (IDA's column padding is not
  something anyone types). Smartcase; `regex` available over RPC.
* **bytes** is IDA's own `find_bytes`, so the pattern language people
  already know works unchanged: hex pairs, `?` wildcards for a whole byte
  or one nibble (`48 8? ?? 24`), quoted literals (`"Hello", 0`). Commas,
  no separators (`488B05C3`) and ragged spacing all normalise.

**Which mode you meant is guessed, and the guess is biased on purpose.**
`dead`, `add`, `cafe` and `ff` are valid hex AND ordinary things to search
for, so a bare hex-looking word stays TEXT; nobody types `48 8b ?? c3`
meaning prose. `hex:`/`text:` prefixes and F2 override it.

The subtle case is a *typo* in a byte pattern. `48 zz c3` first fell
through to a text search and reported "no match" — indistinguishable from
"those bytes are not in this binary", which is the most misleading answer
a search can give. Now any query whose tokens are all byte-sized is
treated as bytes, and a bad token is refused BY NAME. IDA does the same
thing quietly (find_bytes answers a malformed pattern with zero hits and
no error), so the validation lives in Program.search, not just in the UI.

Enter searches, then Enter opens the highlighted hit; the title says which
it will do, because a database-wide scan is far too slow to run on every
keystroke like the other palettes. Navigation goes to the item head — a
byte match can start mid-instruction — and the status names the exact
address.

Also: the `find` RPC verb and `drive find`, which is the one an agent
wants (`drive find '48 8b ?? c3'`).

idatui/search.py holds the classification and is pure, so the whole
question of "what did they mean" is tested offline: tests/test_search.py,
35 checks, 0.1s. Pilot scenario db_search covers the UI end to end.

Full suite: 890 passed, 0 failed, 51.3s.
</content>
</entry>
</feed>
