[PR #1090] [MERGED] fix(apple): admit only compatible dyld subcache mappings #2638

Closed
opened 2026-10-17 21:08:29 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

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

Base: feat/dyld-shared-cache ← Head: cursor/dyld-shared-cache-cleanup-d298


📝 Commits (1)

  • 78d3ce3 fix(apple): admit only compatible dyld subcache mappings

📊 Changes

6 files changed (+186 additions, -16 deletions)

View changed files

📝 src/artifacts/apple/DyldSharedCacheReader.ts (+56 -6)
📝 src/artifacts/apple/DylibResolutionReader.ts (+1 -0)
📝 src/domain/apple/dylibResolution.test.ts (+33 -0)
📝 src/domain/apple/dylibResolution.ts (+18 -8)
📝 src/domain/apple/dylibResolutionSchema.ts (+10 -2)
📝 tests/boundary/filesystem/dyldSharedCache.test.ts (+68 -0)

📄 Description

Summary

Follow-up to #947. Subcache admission was a growing list of special cases after a UUID match, and a trace reported shared-cache whenever an install path fell inside a mapping. Companions now have to agree with the main cache before their mappings are used, and a cache hit has to be a Mach-O the process can load.

Problem and expected behavior

A same-UUID subcache whose dyld_v1 magic names another architecture, or whose mapping base disagrees with the main header's cacheVMOffset, was marked present and its mappings were published. A listed image whose bytes are not a compatible Mach-O was still a definitive shared-cache load because locate only checked range containment.

A companion is admitted only when its UUID, magic, and mapping base agree with the main cache. A UUID miss stays partial coverage. A matching UUID that contradicts the main header is a format error and contributes no mappings. Tracing reports shared-cache only after those bytes parse as a slice the process can load; otherwise the path is undetermined and coverage is partial. Cached load commands stay leaves and are not traversed.

Change and scope

DyldSharedCache.#admitSubcache is the single admission decision for UUID, architecture, and VM offset. Overlap and unmapped-image checks still apply to the admitted set. The trace view's image reads the mapped Mach-O; the domain confirms a compatible slice without storing those facts, so cache-backed images remain leaves.

Not included: new subcache status values, nested traversal of cached dependencies, or changes to disk-override wording.

Contract and boundary impact

  • Semantic owner and earliest changed stage: apple artifact reader admission, then domain candidate evaluation.
  • CLI and MCP/tool-catalog contract: no schema or catalog change. inspect_dyld_shared_cache now fails with reason format for a same-UUID subcache whose architecture or VM offset disagrees. trace_dylib_resolution reports undetermined instead of shared-cache when mapped bytes are not a compatible Mach-O.
  • Provider, bridge, target-format, or platform compatibility: dyld shared-cache file sets only.
  • Evidence, artifact, provenance, or reconstruction contract: none. Caller-selected cache paths are unchanged.
  • Process execution, authorization, cleanup, or containment impact: none.
  • Generated metadata (docs/product-catalog.json), package, or installation impact: none.

Evidence and regression coverage

  • Tests added or updated: tests/boundary/filesystem/dyldSharedCache.test.ts (architecture mismatch, VM-offset mismatch, non-Mach-O cache image, overlap still requires a consistent VM offset) and src/domain/apple/dylibResolution.test.ts (mapped non-Mach-O and wrong-architecture bytes are not loads).
  • Base reproduction or other evidence: on feat/dyld-shared-cache, those companions were admitted and a zero-filled mapped image traced as shared-cache.
  • User-visible CLI/MCP output (if applicable): format errors name the subcache suffix and the disagreed architecture or mapping base. Undetermined cache images appear in coverage.unverified_shared_cache_images.
  • Remaining proof gaps: no real macOS dyld shared cache was inspected in this environment.

For evidence-bearing changes:

  • 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

  • npm run test:focused -- src/domain/apple/dylibResolution.test.ts tests/boundary/filesystem/dyldSharedCache.test.ts tests/boundary/cli/dylibResolutionCli.test.ts tests/boundary/mcp/dyldSharedCacheMcp.test.ts — passed after the overlap fixture kept its VM offset consistent with the overlapped mapping (37 tests on the final revision; the CLI and MCP files passed on the same source).
  • npm run check:fast — passed (pre-push hook).

Real Hopper, Ghidra, and Apple dyld shared-cache verification was not run. This environment has no macOS cache or those engines.

Compatibility, safety, and release

  • Breaking changes or migration steps: none for a released contract. On the unreleased #947 branch, internally inconsistent subcaches that used to inspect as present now fail open, and non-Mach-O mapped paths no longer resolve as shared-cache.
  • Real Hopper/Ghidra, browser, or OS coverage: not run.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: local file reads only; no new process or network authority.

Review checklist

  • 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.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.
Open in Web Open in Cursor 

🔄 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/1090 **Author:** [@morluto](https://github.com/morluto) **Created:** 10/8/2026 **Status:** ✅ Merged **Merged:** 10/8/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `feat/dyld-shared-cache` ← **Head:** `cursor/dyld-shared-cache-cleanup-d298` --- ### 📝 Commits (1) - [`78d3ce3`](https://github.com/morluto/rea/commit/78d3ce35305c03d19143309c92c81c8ecac247e3) fix(apple): admit only compatible dyld subcache mappings ### 📊 Changes **6 files changed** (+186 additions, -16 deletions) <details> <summary>View changed files</summary> 📝 `src/artifacts/apple/DyldSharedCacheReader.ts` (+56 -6) 📝 `src/artifacts/apple/DylibResolutionReader.ts` (+1 -0) 📝 `src/domain/apple/dylibResolution.test.ts` (+33 -0) 📝 `src/domain/apple/dylibResolution.ts` (+18 -8) 📝 `src/domain/apple/dylibResolutionSchema.ts` (+10 -2) 📝 `tests/boundary/filesystem/dyldSharedCache.test.ts` (+68 -0) </details> ### 📄 Description <!-- CURSOR_AGENT_PR_BODY_BEGIN --> ## Summary Follow-up to #947. Subcache admission was a growing list of special cases after a UUID match, and a trace reported `shared-cache` whenever an install path fell inside a mapping. Companions now have to agree with the main cache before their mappings are used, and a cache hit has to be a Mach-O the process can load. ## Problem and expected behavior A same-UUID subcache whose `dyld_v1` magic names another architecture, or whose mapping base disagrees with the main header's `cacheVMOffset`, was marked present and its mappings were published. A listed image whose bytes are not a compatible Mach-O was still a definitive `shared-cache` load because `locate` only checked range containment. A companion is admitted only when its UUID, magic, and mapping base agree with the main cache. A UUID miss stays partial coverage. A matching UUID that contradicts the main header is a format error and contributes no mappings. Tracing reports `shared-cache` only after those bytes parse as a slice the process can load; otherwise the path is undetermined and coverage is partial. Cached load commands stay leaves and are not traversed. ## Change and scope `DyldSharedCache.#admitSubcache` is the single admission decision for UUID, architecture, and VM offset. Overlap and unmapped-image checks still apply to the admitted set. The trace view's `image` reads the mapped Mach-O; the domain confirms a compatible slice without storing those facts, so cache-backed images remain leaves. Not included: new subcache status values, nested traversal of cached dependencies, or changes to disk-override wording. ## Contract and boundary impact - Semantic owner and earliest changed stage: apple artifact reader admission, then domain candidate evaluation. - CLI and MCP/tool-catalog contract: no schema or catalog change. `inspect_dyld_shared_cache` now fails with reason `format` for a same-UUID subcache whose architecture or VM offset disagrees. `trace_dylib_resolution` reports `undetermined` instead of `shared-cache` when mapped bytes are not a compatible Mach-O. - Provider, bridge, target-format, or platform compatibility: dyld shared-cache file sets only. - Evidence, artifact, provenance, or reconstruction contract: none. Caller-selected cache paths are unchanged. - Process execution, authorization, cleanup, or containment impact: none. - Generated metadata (`docs/product-catalog.json`), package, or installation impact: none. ## Evidence and regression coverage - Tests added or updated: `tests/boundary/filesystem/dyldSharedCache.test.ts` (architecture mismatch, VM-offset mismatch, non-Mach-O cache image, overlap still requires a consistent VM offset) and `src/domain/apple/dylibResolution.test.ts` (mapped non-Mach-O and wrong-architecture bytes are not loads). - Base reproduction or other evidence: on `feat/dyld-shared-cache`, those companions were admitted and a zero-filled mapped image traced as `shared-cache`. - User-visible CLI/MCP output (if applicable): format errors name the subcache suffix and the disagreed architecture or mapping base. Undetermined cache images appear in `coverage.unverified_shared_cache_images`. - Remaining proof gaps: no real macOS dyld shared cache was inspected in this environment. For evidence-bearing changes: - [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 - `npm run test:focused -- src/domain/apple/dylibResolution.test.ts tests/boundary/filesystem/dyldSharedCache.test.ts tests/boundary/cli/dylibResolutionCli.test.ts tests/boundary/mcp/dyldSharedCacheMcp.test.ts` — passed after the overlap fixture kept its VM offset consistent with the overlapped mapping (37 tests on the final revision; the CLI and MCP files passed on the same source). - `npm run check:fast` — passed (pre-push hook). Real Hopper, Ghidra, and Apple dyld shared-cache verification was not run. This environment has no macOS cache or those engines. ## Compatibility, safety, and release - Breaking changes or migration steps: none for a released contract. On the unreleased #947 branch, internally inconsistent subcaches that used to inspect as present now fail open, and non-Mach-O mapped paths no longer resolve as `shared-cache`. - Real Hopper/Ghidra, browser, or OS coverage: not run. - Package or release metadata impact: none. - Security, privacy, process, or containment review: local file reads only; no new process or network authority. ## Review checklist - [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] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-b50166c8-2750-4725-adf5-16ed0e97d298?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-b50166c8-2750-4725-adf5-16ed0e97d298&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-17 21:08:29 +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#2638
No description provided.