[PR #1876] [MERGED] fix(android): preserve executable static initializer evidence #4871

Closed
opened 2026-10-31 00:56:15 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1876
Author: @N0zoM1z0
Created: 10/11/2026
Status: ✅ Merged
Merged: 10/11/2026
Merged by: @N0zoM1z0

Base: main ← Head: fix/1846-android-initializer-evidence


📝 Commits (1)

  • 5b065df fix(android): preserve executable static initializer evidence

📊 Changes

10 files changed (+342 additions, -8 deletions)

View changed files

📝 bridge/android/ReaJadxBridge.java (+16 -2)
📝 docs/android-analysis.md (+6 -0)
📝 scripts/verify/android/analysis.mjs (+14 -3)
➕ scripts/verify/android/digest.mjs (+9 -0)
➕ scripts/verify/android/initializers.mjs (+130 -0)
📝 scripts/verify/android/metadata.mjs (+19 -0)
📝 scripts/verify/android/windows-lifecycle.mjs (+16 -3)
📝 tests/conformance/android/ReaJadxMetadataRegression.java (+86 -0)
➕ tests/fixtures/android/static-initializers/InitializationPolicy.smali (+25 -0)
➕ tests/fixtures/android/static-initializers/MixedInitialization.smali (+21 -0)

📄 Description

Summary

REA could report an executable Android static initializer as unavailable, or return only a surviving Java static block while omitting field assignments. Return the exact <clinit>()V smali body, marked static_initializer_disassembly, so both folded assignments and remaining calls are available together.

Closes #1846.

Problem and change

Java generation can relocate initializer instructions into field declarations. A nonempty Java method body therefore does not establish initializer coverage. The REA bridge selects the original method identity and requires one disassembly block; it preserves the engine's existing source byte limit and truncation marker. Ordinary method decompilation and overloaded-smali rejection remain in place.

The real Android verifier now assembles two source-owned DEX fixtures with the audited engine's existing assembler. It checks completely folded initialization and mixed field/static-block initialization through the bridge and public CLI/MCP. Its stale runtime-helper imports are updated to the current configuration boundary and a streaming verifier digest.

Contract and boundary impact

  • Owner: Android provider bridge, before source projection. Public inputs and result schemas are unchanged; static initializer output uses the already-supported smali representation and an explicit reason marker.
  • Evidence: retains method/overload identity, original observations, artifact/engine digests, and incomplete-text reporting. Disassembly is static evidence and does not establish runtime behavior.
  • Process, authorization and containment: existing owned-worker lifecycle; target APKs are never launched. Fixture DEX/APK bytes are generated in an owned temporary directory and removed.
  • Package/generated metadata: no package, installation or catalog contract changes; no generated binaries are committed.

Evidence and validation

  • The added real-engine regression failed on the base bridge. Source investigation also confirmed the mixed case can have a nonempty Java method body while its field assignment is absent.
  • npm run verify:android — passed, including cold metadata, stable overloads, both initializer cases through actual CLI/MCP, ordinary Java methods, no fabricated executable native/abstract bodies, byte-limited disassembly, cancellation/cleanup and failure recovery.
  • Final initializer regression — passed after adding an explicit byte-prefix check.
  • Original reported APK — CLI/MCP return matching initializer instructions, the field assignment and all eleven whitelist strings; following MCP ping succeeds and APK digest is unchanged.
  • Seven focused Android suites — 35 tests passed, including transport, partial observations, selector errors and cleanup.
  • npm run build:cached, npm run check, npm run docs:check and git diff --check — passed.

Compatibility and proof gaps

Verified with the audited Android engine 0.7.1 on Linux x86_64, Node.js 24.18.0 and JDK 21, under one CPU / 3 GiB with a configured 768-MiB Java heap. Native Windows/macOS execution was not performed locally; the Windows verifier's configuration calls now match the runtime API. No new non-Android provider claim or runtime-execution capability is made.

  • Observations, derivations and unknowns remain distinguishable.
  • Artifact identity, provenance and partial evidence remain preserved.
  • One concrete issue, Conventional Commit title, meaningful regression and owning documentation.
  • Final diff contains no credentials, private artifacts or generated binaries.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/1876 **Author:** [@N0zoM1z0](https://github.com/N0zoM1z0) **Created:** 10/11/2026 **Status:** ✅ Merged **Merged:** 10/11/2026 **Merged by:** [@N0zoM1z0](https://github.com/N0zoM1z0) **Base:** `main` ← **Head:** `fix/1846-android-initializer-evidence` --- ### 📝 Commits (1) - [`5b065df`](https://github.com/morluto/rea/commit/5b065df1bc68ab334cd11d2b6cd3dafb586f6d18) fix(android): preserve executable static initializer evidence ### 📊 Changes **10 files changed** (+342 additions, -8 deletions) <details> <summary>View changed files</summary> 📝 `bridge/android/ReaJadxBridge.java` (+16 -2) 📝 `docs/android-analysis.md` (+6 -0) 📝 `scripts/verify/android/analysis.mjs` (+14 -3) ➕ `scripts/verify/android/digest.mjs` (+9 -0) ➕ `scripts/verify/android/initializers.mjs` (+130 -0) 📝 `scripts/verify/android/metadata.mjs` (+19 -0) 📝 `scripts/verify/android/windows-lifecycle.mjs` (+16 -3) 📝 `tests/conformance/android/ReaJadxMetadataRegression.java` (+86 -0) ➕ `tests/fixtures/android/static-initializers/InitializationPolicy.smali` (+25 -0) ➕ `tests/fixtures/android/static-initializers/MixedInitialization.smali` (+21 -0) </details> ### 📄 Description ## Summary REA could report an executable Android static initializer as unavailable, or return only a surviving Java static block while omitting field assignments. Return the exact `<clinit>()V` smali body, marked `static_initializer_disassembly`, so both folded assignments and remaining calls are available together. Closes #1846. ## Problem and change Java generation can relocate initializer instructions into field declarations. A nonempty Java method body therefore does not establish initializer coverage. The REA bridge selects the original method identity and requires one disassembly block; it preserves the engine's existing source byte limit and truncation marker. Ordinary method decompilation and overloaded-smali rejection remain in place. The real Android verifier now assembles two source-owned DEX fixtures with the audited engine's existing assembler. It checks completely folded initialization and mixed field/static-block initialization through the bridge and public CLI/MCP. Its stale runtime-helper imports are updated to the current configuration boundary and a streaming verifier digest. ## Contract and boundary impact - Owner: Android provider bridge, before source projection. Public inputs and result schemas are unchanged; static initializer output uses the already-supported smali representation and an explicit reason marker. - Evidence: retains method/overload identity, original observations, artifact/engine digests, and incomplete-text reporting. Disassembly is static evidence and does not establish runtime behavior. - Process, authorization and containment: existing owned-worker lifecycle; target APKs are never launched. Fixture DEX/APK bytes are generated in an owned temporary directory and removed. - Package/generated metadata: no package, installation or catalog contract changes; no generated binaries are committed. ## Evidence and validation - The added real-engine regression failed on the base bridge. Source investigation also confirmed the mixed case can have a nonempty Java method body while its field assignment is absent. - `npm run verify:android` — passed, including cold metadata, stable overloads, both initializer cases through actual CLI/MCP, ordinary Java methods, no fabricated executable native/abstract bodies, byte-limited disassembly, cancellation/cleanup and failure recovery. - Final initializer regression — passed after adding an explicit byte-prefix check. - Original reported APK — CLI/MCP return matching initializer instructions, the field assignment and all eleven whitelist strings; following MCP ping succeeds and APK digest is unchanged. - Seven focused Android suites — 35 tests passed, including transport, partial observations, selector errors and cleanup. - `npm run build:cached`, `npm run check`, `npm run docs:check` and `git diff --check` — passed. ## Compatibility and proof gaps Verified with the audited Android engine 0.7.1 on Linux x86_64, Node.js 24.18.0 and JDK 21, under one CPU / 3 GiB with a configured 768-MiB Java heap. Native Windows/macOS execution was not performed locally; the Windows verifier's configuration calls now match the runtime API. No new non-Android provider claim or runtime-execution capability is made. - [x] Observations, derivations and unknowns remain distinguishable. - [x] Artifact identity, provenance and partial evidence remain preserved. - [x] One concrete issue, Conventional Commit title, meaningful regression and owning documentation. - [x] Final diff contains no credentials, private artifacts or generated binaries. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 00:56:15 +00:00
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#4871
No description provided.