Repository navigation
fix(findrefs): resolve a string match through its own string_data_item - #56
Merged
Merged
Conversation
fix(findrefs,listclass): bound exact-member scan, decode names as MUTF-8
1. Refactor the asc client to enhance code robustness and break down the god class. 2. Add support for finding extends and implements to findrefs. 3. Update the benchmark.
Rust version: This project has been rewritten 1:1 in Rust as rust_ASC. The Rust version is 10× faster and supports full APK decompilation: with 16 threads, it decompiles a 383 MB APK in just 4 seconds. ASC and rust_ASC will be updated in sync going forward. If your workflow is written in Python, you can continue integrating with this project; it remains the fastest Python Android decompiler available. If you only need a binary, please use rust_ASC.
perf: prefix-only DEX inflate for faster class lookup
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.
Owner
|
貌似有性能劣化,两个测试集没过,要不优化一下? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #54.
Root cause
StringLocatorassumed two things that the DEX format does not require:string_data_items are written back to back, so the first and laststring_idsentry bound the region;string_idsorder, so the item behind a match carriesindex + 1— which let the locator map a match through the following offset and subtract one.d8/R8 satisfy both, but a layout pass such as dexlayout permutes the items, and vendor tools repackage system APKs that way. A synthetic DEX whose
string_datais permuted (offsets, signature and checksum rewritten, code unchanged) shows both failure modes from the report:start > end, every query returns nothingfirst→{1}instead of{3}Fix
0x00on its own. A match that reaches past that terminator runs into the following item and names no string.bisectinstead, and the layout is decided once while building the map.unpack_fromcalls, and fills the lookup withupdate(zip(...)).Tests
tests/test_string_locator_order.pycovers the ordered, reversed and middle-permutation layouts, a substring that must map to the item that holds it, a match that spans two items, and thefindrefsoutput for the reversed layout.tests/dex_fixture.pygainsreorder_string_data(), which moves the items inside their region and recomputes the SHA-1 signature and Adler-32 checksum, so the result stays a valid DEX — the test asserts that every index still resolves to the same string before using it.Verification
string_locator.pyto9216fe2makes the new file fail 13 subtests; with the fix all 7 pass.tests/run_tests.py --suite unit: 72 tests pass (65 existing + 7 new).tests/run_tests.py --suite integration: 5 tests pass.tests/benchmark_compare.py --baseline <base> --samples 15 --cases unit: no gated regression.unit/string_locator−35%,unit/type_locator−4%,unit/method_locator+2.5% (p=0.30),unit/field_locator+2.0% (p=0.30).tests/benchmark_reference.py --samples 3: all 16 count metrics matchreference-baseline.json.Not verified here: the GUI suite (this machine is Windows with no Tk display), and
benchmark_reference.py's 0.0880 s decompilation budget, which the base commit misses on this machine as well (0.28 s vs 0.33 s) — the recorded baseline is a Linux CI number and the decompiler path is untouched.Note
The end of an item is still taken as the start of the next one:
string_data_itemhas no alignment requirement and both d8 and dexlayout write the items back to back. A layout that pads between items falls back to the search path, which bounds the item by the following offset.