[PR #5791] [CLOSED] fix(apple): keep wide archive integers a table entry aliases #7066

Closed
opened 2026-11-01 21:45:07 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/5791
Author: @charan-rathore
Created: 10/21/2026
Status: ❌ Closed

Base: main ← Head: fix/5783-wide-integer-table-alias


📝 Commits (4)

  • fbb14c2 fix(apple): keep wide archive integers a table entry aliases
  • f2ca695 fix(apple): keep wide archive integers a table entry aliases
  • d727e0a fix(apple): keep wide archive integers a table entry aliases
  • 4ace658 fix(apple): keep wide archive integers a table entry aliases

📊 Changes

4 files changed (+173 additions, -27 deletions)

View changed files

📝 src/artifacts/apple/KeyedArchiveReader.test.ts (+33 -0)
📝 src/artifacts/apple/KeyedArchiveReader.ts (+68 -11)
📝 src/artifacts/apple/PlistNumberLiterals.test.ts (+31 -1)
📝 src/artifacts/apple/PlistNumberLiterals.ts (+41 -15)

📄 Description

Summary

Fixes #5783. inspect-keyed-archive reported a valid 16-byte integer as a small fragment (13119) when a date object's offset-table entry aliased into the integer's payload. The scanner validated each object against the next table offset, so one aliasing entry dropped all number metadata for the file, and the in-place byte rewrite could not cover the aliased integer without corrupting the date sibling.

Problem and expected behavior

Trigger: a binary NSKeyedArchiver where one object is a 16-byte integer and another object's table entry points inside that integer's 9-byte rewrite range. plutil and Python accept the overlap. Violated invariant: exact integer metadata was lost for the whole file, and the wide integer decoded as the signed value of its first 8 payload bytes.

Change and scope

  • PlistNumberLiterals: validate each unique object offset against the offset table itself. An entry starting inside a prior object's extent is contained: it is skipped for number metadata and the result is marked incomplete. A wide integer now records conflicted when another table entry lies in its 9-byte rewrite range, and decodeBinaryPlistNumbers rewrites only non-conflicted integers.
  • KeyedArchiveReader: for conflicted wide integers, match the pinned decoder's signed first-8-bytes fragment on the decoder's own input copy and restore the exact decimal at the matching $objects positions, only when every fragment position is accounted for. Aliased siblings keep their own bytes and decode.
  • Not included: date decode paths unchanged; no byte rewrite for conflicted integers (rewriting would corrupt the aliased sibling). Ordinary fix within existing boundaries; scope decision not applicable.

Contract and boundary impact

  • Semantic owner and earliest changed stage: apple artifact decoding, binary plist number metadata
  • Contribution scope fit and linked maintainer decision: not applicable
  • CLI and MCP/tool-catalog contract: no shape change; decoded values only
  • Provider, bridge, target-format, or platform compatibility: none
  • Evidence, artifact, provenance, or reconstruction contract: exact decimals restored where the decoder cannot represent them; caller's buffer untouched
  • Target selection, authority, upstream behavior, and cleanup details (if applicable): not applicable
  • Generated metadata, package, or installation impact: none

Expected effects:

  • Read existing files or captured data.

Evidence and regression coverage

  • Tests added or updated: scanner test (aliased wide integer kept, marked conflicted, bytes untouched) and archive-reader test (exact decimal restored for both the ordinary and aliased fixtures; date sibling decodes identically). Fixtures follow the #5783 python plistlib recipe with value 242016218615821083930112.

  • Base reproduction or other evidence: both new tests fail on the parent commit (reader surfaces the 13183 fragment, scanner drops the integer); both pass with the change.

  • User-visible CLI/MCP output (if applicable): none

  • Remaining proof gaps: repo-wide turbo typecheck, lint and knip not run

  • Observed, derived, and inferred claims remain distinguishable.

  • Artifact identity, source provenance, and failed attempts remain preserved.

  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • node_modules/.bin/vitest run src/artifacts/apple src/domain/apple - 15 files, 315 tests passed, including the two new tests
  • node_modules/.bin/vitest run on the two touched test files with the two source files reverted - exactly the two new tests fail (RED check)
  • node_modules/.bin/oxfmt --check on touched files - clean
  • node_modules/.bin/oxlint on touched files - 0 errors, warnings at base parity
  • npm run check (turbo typecheck, lint, knip) - not run; scoped checks only

Compatibility, safety, and release

  • Breaking changes or migration steps: none
  • Real Hopper/Ghidra, browser, or OS coverage: not applicable
  • Package or release metadata impact: none
  • Security, privacy, process, or containment review: none; decode-only change on already-accepted input

Author readiness

Human owner: @charan-rathore

AI-assisted; Charan Rathore is the human driver. Readiness declarations are left for the human owner per the template, so this opens as a draft.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🔄 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/5791 **Author:** [@charan-rathore](https://github.com/charan-rathore) **Created:** 10/21/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/5783-wide-integer-table-alias` --- ### 📝 Commits (4) - [`fbb14c2`](https://github.com/morluto/rea/commit/fbb14c25c4220108902a8df3b2fcf3acd1a4acd0) fix(apple): keep wide archive integers a table entry aliases - [`f2ca695`](https://github.com/morluto/rea/commit/f2ca6958aa8d0a3b2f34f3e70b14f918b7ec12e4) fix(apple): keep wide archive integers a table entry aliases - [`d727e0a`](https://github.com/morluto/rea/commit/d727e0a5e1b925b1d32c1fef391b508b75198368) fix(apple): keep wide archive integers a table entry aliases - [`4ace658`](https://github.com/morluto/rea/commit/4ace658f44d90408aa7633e347a73b8e099a785e) fix(apple): keep wide archive integers a table entry aliases ### 📊 Changes **4 files changed** (+173 additions, -27 deletions) <details> <summary>View changed files</summary> 📝 `src/artifacts/apple/KeyedArchiveReader.test.ts` (+33 -0) 📝 `src/artifacts/apple/KeyedArchiveReader.ts` (+68 -11) 📝 `src/artifacts/apple/PlistNumberLiterals.test.ts` (+31 -1) 📝 `src/artifacts/apple/PlistNumberLiterals.ts` (+41 -15) </details> ### 📄 Description ## Summary Fixes #5783. inspect-keyed-archive reported a valid 16-byte integer as a small fragment (13119) when a date object's offset-table entry aliased into the integer's payload. The scanner validated each object against the next table offset, so one aliasing entry dropped all number metadata for the file, and the in-place byte rewrite could not cover the aliased integer without corrupting the date sibling. ## Problem and expected behavior Trigger: a binary NSKeyedArchiver where one object is a 16-byte integer and another object's table entry points inside that integer's 9-byte rewrite range. plutil and Python accept the overlap. Violated invariant: exact integer metadata was lost for the whole file, and the wide integer decoded as the signed value of its first 8 payload bytes. ## Change and scope - PlistNumberLiterals: validate each unique object offset against the offset table itself. An entry starting inside a prior object's extent is contained: it is skipped for number metadata and the result is marked incomplete. A wide integer now records conflicted when another table entry lies in its 9-byte rewrite range, and decodeBinaryPlistNumbers rewrites only non-conflicted integers. - KeyedArchiveReader: for conflicted wide integers, match the pinned decoder's signed first-8-bytes fragment on the decoder's own input copy and restore the exact decimal at the matching $objects positions, only when every fragment position is accounted for. Aliased siblings keep their own bytes and decode. - Not included: date decode paths unchanged; no byte rewrite for conflicted integers (rewriting would corrupt the aliased sibling). Ordinary fix within existing boundaries; scope decision not applicable. ## Contract and boundary impact - Semantic owner and earliest changed stage: apple artifact decoding, binary plist number metadata - Contribution scope fit and linked maintainer decision: not applicable - CLI and MCP/tool-catalog contract: no shape change; decoded values only - Provider, bridge, target-format, or platform compatibility: none - Evidence, artifact, provenance, or reconstruction contract: exact decimals restored where the decoder cannot represent them; caller's buffer untouched - Target selection, authority, upstream behavior, and cleanup details (if applicable): not applicable - Generated metadata, package, or installation impact: none Expected effects: - [x] Read existing files or captured data. ## Evidence and regression coverage - Tests added or updated: scanner test (aliased wide integer kept, marked conflicted, bytes untouched) and archive-reader test (exact decimal restored for both the ordinary and aliased fixtures; date sibling decodes identically). Fixtures follow the #5783 python plistlib recipe with value 242016218615821083930112. - Base reproduction or other evidence: both new tests fail on the parent commit (reader surfaces the 13183 fragment, scanner drops the integer); both pass with the change. - User-visible CLI/MCP output (if applicable): none - Remaining proof gaps: repo-wide turbo typecheck, lint and knip not run - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - `node_modules/.bin/vitest run src/artifacts/apple src/domain/apple` - 15 files, 315 tests passed, including the two new tests - `node_modules/.bin/vitest run` on the two touched test files with the two source files reverted - exactly the two new tests fail (RED check) - `node_modules/.bin/oxfmt --check` on touched files - clean - `node_modules/.bin/oxlint` on touched files - 0 errors, warnings at base parity - `npm run check` (turbo typecheck, lint, knip) - not run; scoped checks only ## Compatibility, safety, and release - Breaking changes or migration steps: none - Real Hopper/Ghidra, browser, or OS coverage: not applicable - Package or release metadata impact: none - Security, privacy, process, or containment review: none; decode-only change on already-accepted input ## Author readiness Human owner: @charan-rathore AI-assisted; Charan Rathore is the human driver. Readiness declarations are left for the human owner per the template, so this opens as a draft. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-11-01 21:45:07 +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#7066
No description provided.