Skip to content

feat: add liststring CLI command and MCP tool - #6

Merged
MG1937 merged 1 commit into
MG1937:devfrom
TsingShui:feat/liststring
Oct 21, 2026
Merged

MG1937 merged 1 commit into
MG1937:devfrom
TsingShui:feat/liststring

Conversation

@TsingShui

@TsingShui TsingShui commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

概述

新增 liststring:列出 APK 内每个 DEX 字符串池的值(CLI + MCP 工具),可选大小写不敏感子串过滤。

本 PR 只有 1 个 commit,仅包含源码、测试和 README;

主要实现

  • 枚举口径:直接遍历 string_ids 表(而非 class_defs),所以不依赖字符串物理顺序,也不受“必须被引用”限制;输出顺序为 DEX 中心目录序 + string index(即 findrefs 行解析所用的索引),跨 DEX 重复保留。
  • 复用匹配器:过滤谓词复用 findrefs 的 matches_name(pub(crate) 提升可见性,逻辑零改动),ASCII 走 memchr2 + 忽略大小写字节比较、非 ASCII 走 MUTF-8 解码 + lowercase contains。这样“能列出的字符串”和“能定位的字符串”对“包含”的判定必然一致。
  • 复用管线:走既有的有序流式管线(_stream_dex_items),并行解压、按中心目录顺序输出、有界保留;DEX 041 容器会对每个逻辑 DEX 各列一次。未新增线程、队列或缓存。
  • record 与行分开:ApkHandler::list_strings 返回 Result<Vec<String>, String>,一个元素 = 一个字符串(值内换行不拆分);CLI/MCP 则是一行一值,值内含换行会自然断行,与 findrefs 的 matched=(...) 行为一致,README 已注明。
  • MCP:liststring 工具(apk_path / filter / thread / output),与 listclass/listmethod 一致地转成 CLI 调用,返回值即 CLI stdout。

验证

  • cargo test --release:88 个测试通过(新增 9 个:3 个 CLI + 6 个库 API,覆盖过滤、UTF-8 大小写折叠、值内换行/制表符的 record 边界、DEX 041 容器、非 DEX 载荷报错、Stored/Deflated 与 1/2/4 线程)。
  • 与 rxd dex strings 对淘宝 **10.66.40(91 MiB)**交叉比对:逐 DEX 字符串条数 完全一致(13 个 DEX,合计 908,386 条,diff 为空)。
  • 过滤结果集对齐:mtop 5059 条 / https 2230 条 / 中文 9 条 与 rxd 一致;行数差全部可由“值内换行”解释(5182 = 5059 + 123,2730 = 2230 + 500)。
  • 确定性:--thread 1 与 --thread 8、以及重复运行的全量输出 SHA-1 相同。
  • 未引入格式噪声:cargo fmt 造成的整仓重排已回退,diff 仅含本功能相关 hunk。

- List DEX string pool values in table order, optionally narrowed by a case insensitive substring that reuses the findrefs string matcher, so a listed and a located string agree on what a filter matches.
- Reuse the ordered listclass/listmethod streaming pipeline: entries inflate in parallel and emit in central directory order, and DEX 041 containers list every logical pool.
- Read the pool from string_ids instead of class or method data, so literals nothing references are listed too. findrefs string cannot answer which literals exist: an empty result there means no reference rather than not present.
- Keep records and lines distinct: ApkHandler::list_strings returns one element per string, while the CLI writes one value per line, so a value containing a newline spans several lines exactly as a findrefs matched payload does.
- Add regression coverage for filters, UTF-8 folds, record boundaries, DEX 041 containers, broken entries and MCP argument mapping.

Validation: cargo test --release (88 tests), plus identical per DEX string counts and identical filtered sets against rxd dex strings on a 91 MB APK (908,386 strings across 13 DEX).
@MG1937
MG1937 merged commit e2d3fb9 into MG1937:dev Oct 21, 2026
3 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