Stop reporting a tool's resource failure as a finding about the target

A JVM reader that dies on a large or deeply nested input -- OutOfMemoryError, an OOM kill, a
container limit, a timeout -- prints an empty result that looks exactly like a reader that read the
file and found nothing. That is the `present but unreadable` case SKILL.md §Coverage names, and it is
where a wrong "that class is not in there" gets recorded.

The new section in toolchain.md says what a failed analysis actually supports (a claim about the
route, not about the artifact) and the three things to check before a negative from a heavy tool
becomes a finding: the exit code and stderr rather than stdout alone, a re-run with room to work, and
the indexed-query route that answers most location questions without materialising anything. A
deadline you set yourself gets the same reading -- it reported nothing about the target.

Also: the README claimed the scripts "work identically on Windows, macOS and Linux", while every gate
run, every test result and every figure in the evidence record comes from one Windows host. The claim
now carries the strength it actually has -- measured on Windows, `unverified` elsewhere -- and names
the usual suspects (path separators, `os.pathsep` in `APKREV_TOOLS`, console encodings, ADB shell
quoting) so a first run on another platform has somewhere to look.
This commit is contained in:
inliver233
2026-10-16 19:20:45 +08:00
parent 6ab905b2c8
commit 5c3ba9cd2e
3 changed files with 33 additions and 1 deletions
+8 -1
View File
@@ -505,9 +505,16 @@ set APKREV_TOOLS=<dir>;<dir> # Windows, e.g. an SDK or proje
export APKREV_TOOLS=<dir>:<dir> # POSIX
```
The scripts themselves are plain `python3` and are intended to work identically on Windows, macOS and
The scripts themselves are plain `python3` and are designed to work identically on Windows, macOS and
Linux; where a snippet is POSIX-only it is labelled. Nothing here assumes a Unix shell.
**Measured on Windows only.** Every gate run, every test result and every figure in the evidence
record comes from one host (Windows 10.0.26100, PowerShell 7, CPython 3.14). Cross-platform behaviour
is a design intention, not an observation: treat another platform as `unverified` until the suite has
been run there, and expect the usual suspects to be the difference — path separators, `os.pathsep` in
`APKREV_TOOLS`, console encodings, and shell quoting in the ADB helpers. If you run the gates on
macOS or Linux and they pass, that is a `observed` result worth recording next to this paragraph.
| Tool | Used for |
|---|---|
| Python 3.9+ | all scripts |
+2
View File
@@ -417,6 +417,8 @@ export APKREV_TOOLS=<dir>:<dir> # POSIX
脚本本身是纯 `python3`,并且意图在 Windows、macOS 和 Linux 上行为一致;凡有片段仅限 POSIX,都会标注出来。这里没有任何东西假定你用的是 Unix shell。
**实测只在 Windows 上做过。** 每一次门禁运行、每一个测试结果、以及证据记录里的每一个数字,都来自同一台主机(Windows 10.0.26100、PowerShell 7、CPython 3.14)。跨平台行为是设计意图,不是观测结果:在别处跑通之前,把另一个平台当作 `unverified`,并预期差异出在几个老地方 —— 路径分隔符、`APKREV_TOOLS` 里的 `os.pathsep`、控制台编码,以及 ADB 辅助脚本里的 shell 引号转义。如果你在 macOS 或 Linux 上跑门禁并通过了,那是一个值得记在这段旁边的 `observed` 结果。
| 工具 | 用途 |
|---|---|
| Python 3.9+ | 所有脚本 |
@@ -270,6 +270,29 @@ line numbers and even which branch is which can differ from the bytecode. When a
it, verify in smali or at runtime. `jadx` writing `(unknown)`/empty method bodies means it failed,
not that the method is empty.
### A tool that ran out of room did not tell you the target is empty
Every JVM-based reader in this list, and several of the native ones, can die on a large or deeply
nested input without saying anything about the artifact: `OutOfMemoryError`, a `Killed` from the OOM
killer, a container limit, or a timeout. The output looks like a tool that read the file and found
nothing — an empty result plus a line most people skim past.
**What a failed analysis supports is a claim about the analysis, not the artifact**: "this route could
not complete on this input" is `present but unreadable` (`SKILL.md` §Coverage), and it is exactly
where a wrong "that class is not in there" gets written into a record. Three things to do before a
negative from a heavy tool becomes a finding:
- read the **exit code and stderr**, not just stdout — a heap death often exits non-zero with a
partial result already printed;
- give the tool the room the input warrants (a larger heap for the JVM readers) and re-run before
concluding anything;
- prefer a route that does not have to materialise everything: an indexed query against the APK
(`rasc`/`droidasc`/`dexsql`) answers most location questions without decompiling a single class, and
it is also the route that survives a target too large for a full export.
The same reading applies to a **time budget** you set yourself: a command you killed at your own
deadline reported nothing about the target, only about your deadline.
**`smali` assembling can abort silently** — the tree produces no dex while the process still exits
0. Never treat exit code as proof of a build. Assert the artifact exists, is fresh, and is non-empty
(`patch-audit.md`).