Skip to content

v0.1.2-post4 - #58

Merged
MG1937 merged 4 commits into
mainfrom
dev-0.1.0
Oct 30, 2026
Merged

MG1937 merged 4 commits into
mainfrom
dev-0.1.0

Conversation

@MG1937

@MG1937 MG1937 commented Oct 30, 2026

Copy link
Copy Markdown
Owner

v0.1.2-post4

Fixed

  • findrefs returned wrong or missing matches on DEX files whose string data is not written in string_ids order.
    StringLocator assumed the string data items were laid out in index order and mapped a match through the offset of the following item, then subtracted one. The DEX format does not require that order, and layout passes such as dexlayout (used when repackaging system APKs) permute the items. As a result:

    • a reversed layout collapsed the search region to start > end, so every string was missed;
    • a partial permutation returned neighbouring indexes, producing false hits such as a getDeviceId query reporting Display.getDeviceProductInfo.

    Method and field lookups that resolve names through the same locator were affected too, not only findrefs string.

    The locator now takes the region from the smallest and largest string_data_off and resolves each match with a binary search over the physical offsets, returning the index of the item that actually holds the match. This matches the asc-rs implementation and makes no assumption about item order.

  • getclass slowdown introduced by smali formatting. Method descriptor normalization moved out of the decompiler hot path and into the smali formatter only, removing repeated string rewriting on every invoke.

Performance

Measured against the previous baseline on the same workload:

Metric Change
unit/string_locator -32.5%
unit/type_locator -56.1%
unit/field_locator -11.2%
unit/method_locator -9.3%
unit/field_locator_fuzzy_class_only -40.5%
unit/field_locator_fuzzy_class_field -18.8%

No gated metric regressed. The new lookup costs one bisect plus one dict hit per match; it needs no terminator scan, which matters on DEX files that embed multi-hundred-kilobyte string payloads (a backwards \x00 scan across such an item was measured ~5x slower on Windows, where memrchr is unavailable).

Tests

  • Added coverage for the ordered layout, a full reversal, and a middle permutation, plus findrefs output equality across layouts.
  • Full suite: 146 tests pass.

Upgrade

No API changes. droidasc is on PyPI; pip install -U droidasc.

Henglie and others added 4 commits October 25, 2026 18:13
StringLocator assumed the string_data_items are written in string_ids order
and back to back: it took the region bounds from the first and last entry,
mapped a match to the offset of the item that follows it, and subtracted one
from that index. The format does not require that layout, and dexlayout (or
the vendor tools that repackage system APKs) permutes the items, so findrefs
returned the wrong methods or nothing at all: a reversed layout collapses the
region to start > end, a partial permutation returns neighbouring indexes.
Method and field queries that resolve names through the locator are affected
the same way.

Take the region from the smallest and largest offset, and end a match at the
first terminator behind its start: a match that reaches past it runs through
the terminator into the following item and names no string. When the offsets
are in index order, the item behind a match still carries the next index and a
single dict lookup resolves it, so d8/r8 output keeps the old cost; a permuted
layout searches the ascending offsets instead. Building the map also stops
unpacking every entry by hand, which leaves the string locator faster than
before (-35% on the supplied DEX workload, no gated regression).

tests/dex_fixture.py gains reorder_string_data(), which rewrites a fixture in
a given order and recomputes the signature and checksum, so the new tests
cover the ordered layout, a full reversal, and a middle permutation, plus the
findrefs output for each.
fix(findrefs): resolve a string match through its own string_data_item
String data items are not written in string_ids order, so mapping a match through the following item and subtracting one returns a wrong index or nothing at all. Take the region from the smallest and largest offset and resolve the match with a binary search over the physical offsets, the same way asc-rs does.

The lookup needs one bisect and one dict hit per match, with no terminator scan. On the reference workload this is faster than the previous neighbour-offset scheme: string_locator -32.5%, type_locator -56.1%, field_locator -11.2%, method_locator -9.3%, no gated regression.
@MG1937
MG1937 merged commit 7f25520 into main Oct 30, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants