[GH-ISSUE #4820] [Bug] Apktool string document failures fabricate one omitted entry #2506

Closed
opened 2026-10-17 21:05:55 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @morluto on GitHub (Oct 17, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/4820

Before submitting

  • Searched open/closed Apktool malformed/count reports; #4694 covers replacement characters, #4777 shared decoding.
  • Removed credentials and sensitive data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

The built string-table parser represents an invalid XML document, a valid document with the wrong root, and one actual unsupported string element identically: {entries: [], unparsedCount: 1}. The provider turns that sentinel into the published limitation String entries omitted due to malformed XML or unsupported markup: 1. The malformed document's entry count was not established.

Reproduction

Executed once per input with pinned Node 24.18.0 against the built runtime at d38f09969:

import { parseDecodedStrings } from './dist/apktool/ApktoolDecodeOutput.js';
for (const xml of [
  '<resources><string name="a">one</string><string name="b">two</resources>',
  '<manifest/>',
  '<resources><string name="styled">hello <b>world</b></string></resources>'
]) console.log(parseDecodedStrings(xml));

All three returned the object above. This is an executed producer-boundary control plus source inspection of provider formatting; no real Apktool/APK/JVM reproduction was run.

Expected behavior

Distinguish a document-level projection failure (malformed syntax or wrong root) from counted unsupported entries in a validated document. Publish the document failure reason and unknown counts; continue reporting actual examined unsupported-entry counts for valid XML. Preserve valid strings, raw source spelling, cancellation and filesystem failure semantics.

Impact and scope

A limitation claims one omitted entry when the whole document failed validation. Existing partial coverage and empty strings are explicit, so this does not establish silent complete coverage or lost good XML. Real target frequency: NOT_ENOUGH_INFO; no APK corpus examined.

REA version

6.5.0, d38f099692

Runtime and platform

Node 24.18.0, macOS arm64

Target and artifact context

Three authored XML strings, built parser only.

Interface

CLI and MCP shared provider (publication behavior source-derived).

Earliest failure stage

Resource projection.

Relevant output or evidence

src/apktool/ApktoolDecodeOutput.ts:84-88 fabricates the count sentinel; ApktoolProvider.ts treats it as an actual unparsed entry count. The only consumers are the provider and parser tests. The shared parseXmlDocument already returns a tagged Result with syntax failure reasons.

Typed outcome or recovery expected

A tagged document-level parsing outcome consumed once by the provider; malformed/wrong-root Evidence remains partial and says the entry count is unknown. Filesystem, cancellation and cleanup errors must retain their existing typed failure paths.

Analysis or suspected cause

Whole-document failure and per-entry omission share one numeric representation. PR #4804 recognizes a malformed distinction, but retains the sentinel and adds a broad read-failure catch; its independent integration and aggregate resource design remain under review in #4777.

Additional context

Existing static resource projection only, no authority expansion. Address this at the producing representation and update all consumers before extending multi-table projection.

Originally created by @morluto on GitHub (Oct 17, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4820 ### Before submitting - [x] Searched open/closed Apktool malformed/count reports; #4694 covers replacement characters, #4777 shared decoding. - [x] Removed credentials and sensitive data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior The built string-table parser represents an invalid XML document, a valid document with the wrong root, and one actual unsupported string element identically: `{entries: [], unparsedCount: 1}`. The provider turns that sentinel into the published limitation `String entries omitted due to malformed XML or unsupported markup: 1`. The malformed document's entry count was not established. ### Reproduction Executed once per input with pinned Node 24.18.0 against the built runtime at d38f09969: ```js import { parseDecodedStrings } from './dist/apktool/ApktoolDecodeOutput.js'; for (const xml of [ '<resources><string name="a">one</string><string name="b">two</resources>', '<manifest/>', '<resources><string name="styled">hello <b>world</b></string></resources>' ]) console.log(parseDecodedStrings(xml)); ``` All three returned the object above. This is an executed producer-boundary control plus source inspection of provider formatting; no real Apktool/APK/JVM reproduction was run. ### Expected behavior Distinguish a document-level projection failure (malformed syntax or wrong root) from counted unsupported entries in a validated document. Publish the document failure reason and unknown counts; continue reporting actual examined unsupported-entry counts for valid XML. Preserve valid strings, raw source spelling, cancellation and filesystem failure semantics. ### Impact and scope A limitation claims one omitted entry when the whole document failed validation. Existing partial coverage and empty strings are explicit, so this does not establish silent complete coverage or lost good XML. Real target frequency: NOT_ENOUGH_INFO; no APK corpus examined. ### REA version 6.5.0, d38f099692394ec90c582f9f0a14b036b421b160 ### Runtime and platform Node 24.18.0, macOS arm64 ### Target and artifact context Three authored XML strings, built parser only. ### Interface CLI and MCP shared provider (publication behavior source-derived). ### Earliest failure stage Resource projection. ### Relevant output or evidence `src/apktool/ApktoolDecodeOutput.ts:84-88` fabricates the count sentinel; `ApktoolProvider.ts` treats it as an actual unparsed entry count. The only consumers are the provider and parser tests. The shared `parseXmlDocument` already returns a tagged Result with syntax failure reasons. ### Typed outcome or recovery expected A tagged document-level parsing outcome consumed once by the provider; malformed/wrong-root Evidence remains partial and says the entry count is unknown. Filesystem, cancellation and cleanup errors must retain their existing typed failure paths. ### Analysis or suspected cause Whole-document failure and per-entry omission share one numeric representation. PR #4804 recognizes a malformed distinction, but retains the sentinel and adds a broad read-failure catch; its independent integration and aggregate resource design remain under review in #4777. ### Additional context Existing static resource projection only, no authority expansion. Address this at the producing representation and update all consumers before extending multi-table projection.
bsakaguchi 2026-10-17 21:05:55 +00:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@morluto commented on GitHub (Oct 17, 2026):

Fixed in dc2e8117b6.

Root cause: the string-document parser represented malformed XML, a wrong document root, and a valid unsupported entry with the same count of one. The provider consequently fabricated an omitted-entry count for unreadable documents.

The canonical XML parser now feeds a tagged Result. Document failures carry their reason/cause; the provider preserves partial Evidence with unknown entry counts. Only valid documents count actual unsupported entries. Removed the superseded throwing XML wrapper and updated both parser consumers. Existing file ownership, cancellation, and cleanup semantics remain intact.

Validation: 229 focused tests across 15 files pass; four regression controls fail against baseline bec88b9d7; typecheck/lint pass. Actual built CLI controls cover valid, malformed, wrong-root, and unsupported-entry documents. Two source reviews cleared the fix. The final docs check also passes after the separate Malayalam repair (#4821).

Twelve completed stdio MCP workflows compare bec88b9d7 with dc2e8117b using an authored inert provider fixture, including full tool discovery, decode, Evidence, and text/structured parity. Warm medians (two alternating repeats/build): malformed elapsed 2.896→2.999 s, CPU 4.054→4.163 s, sampled process-family RSS 1.339→1.353 GB; cl100k task tokens 804426→804464. Valid controls retain identical Evidence and 804429 tokens. First-process runs were recorded separately. No speedup is claimed; true cold caches, transient/reparented memory, whole-agent tokens, and real Apktool/JVM behavior were not verified. Heavy profiling/stress remained stopped.

<!-- gh-comment-id:6235944240 --> @morluto commented on GitHub (Oct 17, 2026): Fixed in dc2e8117b60c4481372ed89b077e6c1cf81ee653. Root cause: the string-document parser represented malformed XML, a wrong document root, and a valid unsupported entry with the same count of one. The provider consequently fabricated an omitted-entry count for unreadable documents. The canonical XML parser now feeds a tagged Result. Document failures carry their reason/cause; the provider preserves partial Evidence with unknown entry counts. Only valid documents count actual unsupported entries. Removed the superseded throwing XML wrapper and updated both parser consumers. Existing file ownership, cancellation, and cleanup semantics remain intact. Validation: 229 focused tests across 15 files pass; four regression controls fail against baseline bec88b9d7; typecheck/lint pass. Actual built CLI controls cover valid, malformed, wrong-root, and unsupported-entry documents. Two source reviews cleared the fix. The final docs check also passes after the separate Malayalam repair (#4821). Twelve completed stdio MCP workflows compare bec88b9d7 with dc2e8117b using an authored inert provider fixture, including full tool discovery, decode, Evidence, and text/structured parity. Warm medians (two alternating repeats/build): malformed elapsed 2.896→2.999 s, CPU 4.054→4.163 s, sampled process-family RSS 1.339→1.353 GB; cl100k task tokens 804426→804464. Valid controls retain identical Evidence and 804429 tokens. First-process runs were recorded separately. No speedup is claimed; true cold caches, transient/reparented memory, whole-agent tokens, and real Apktool/JVM behavior were not verified. Heavy profiling/stress remained stopped.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#2506
No description provided.