Repository navigation
fix(apktool): preserve valid replacement characters in decoded XML - #4697
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
[Medium impact] The PR appears safe to merge; no actionable issue was found. Summary
Reviews (1) · Last reviewed commit: "fix(apktool): preserve valid replacement..." · Reviewed by Greptile |
|
Thanks for spotting that a literal replacement character is valid XML, @ys0v9. Ignoring only that xmldom warning keeps good Apktool strings and package names available while other parse errors still surface. Glad to welcome you to REA. |
Summary
Fixes #4694. Preserve literal U+FFFD (
�) in Apktool-decoded XML so one valid string no longer causes the entire string table to be omitted. The same parser also preserves manifest package extraction when another attribute contains U+FFFD.Problem and expected behavior
For
<resources><string name="good">Hello</string><string name="edge">�</string></resources>, REA returned no strings andcoverage: "partial", although real Apktool decoded both entries. U+FFFD is valid XML and these UTF-8 bytes are valid. Both strings should be returned verbatim with complete coverage for this fixture.Change and scope
At the shared Apktool XML parsing boundary, ignore only xmldom's U+FFFD warning. Keep all other diagnostics as parse failures. The existing fatal UTF-8 decoder continues to reject invalid source bytes. Both consumers use this boundary; no downstream repair or new abstraction is needed.
This is an ordinary fix within the existing resource-analysis boundary. A maintainer scope decision is not applicable.
Contract and boundary impact
ApktoolDecodeOutput.parseXml, decoded XML projection.Expected effects of the existing workflow:
Evidence and regression coverage
5717ad24aa6471aa4207c370e26274866fb8aee5, the new tests produced 3 failures / 46 passes. With this fix, the same selection produced 49 passes.node scripts/rea.mjs decode-android-resources <apk> --json. Each fixture was run twice before and twice after the fix; all CLI exits were 0.edge=plain,good=Hellocompletecompleteedge=�,good=Hellostrings: [];partial�;completeThe prior
String entries omitted due to malformed XML or unsupported markup: 1limitation is absent after the fix. The same failing APK SHA-256 was used before and after:7a43b05965c43e05360cc47bfbac3dc14d606428e7ab34def0188a3a338453c2.Remaining proof gaps: real-tool execution covered macOS arm64 and Apktool 3.0.3 only. The manifest U+FFFD case is covered by parser and simulated-provider tests, not a separate real APK. MCP and other OS/provider versions were not exercised.
Validation performed
npm run test:focused -- src/apktool/ApktoolDecodeOutput.test.ts src/apktool/ApktoolProvider.test.ts— 49 passed.npm run check— passed: typecheck, format, lint, Knip, metadata, module boundaries, and architecture guards. Lint reported 0 errors and 1,615 warnings across the repository.npm run build:cached— passed.git diff --check— passed.Toolchain: Node.js 24.18.0, npm 11.16.0, OpenJDK 21.0.10, Apktool 3.0.3, macOS 26.5.1 arm64. The complete test suite remains for CI; generated-document checks are not applicable because no contract or generated metadata changed.
Compatibility, safety, and release
Author readiness
Human owner: @ys0v9
Before merge
type(scope): outcome.