[PR #4093] [MERGED] fix(native): keep a category whose class reference cannot be read #6051

Closed
opened 2026-10-31 01:11:29 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/4093
Author: @kaoru0822-kitauji
Created: 10/15/2026
Status: ✅ Merged
Merged: 10/15/2026
Merged by: @kaoru0822-kitauji

Base: main ← Head: fix/4012-objc-category-unresolved-class


📝 Commits (1)

  • f67b5a3 fix(native): keep a category whose class reference cannot be read

📊 Changes

2 files changed (+54 additions, -5 deletions)

View changed files

📝 src/native/AppleDispatchMetadata.test.ts (+38 -3)
📝 src/native/AppleObjcCategories.ts (+16 -2)

📄 Description

Summary

Fixes #4012. inspect_native_dispatch_metadata threw away a whole Objective-C category when its nonzero class reference pointed outside mapped metadata. The category's name, method selectors and implementations were readable and were lost with it. The category is now kept: its class identity is reported as unresolved, and category coverage is partial, with the reason.

Problem and expected behavior

decodeObjcCategories called input.localClassName(local) inside the category's single try. For an unmapped reference that call throws, so the record was replaced by a generic category_decode_failed issue. A zero class reference already produces the right shape (class_name: null, class_source: "unresolved", decode partial), so the schema already supports this.

Reproduced with the issue's generated arm64 fixtures through the built CLI. The two fixtures differ only in category_t.cls:

fixture main this PR
cls = 0 (control) category kept (unresolved), 1 implementation, coverage partial, 3,999 bytes unchanged
cls = 0x100005000 (unmapped) no category, 0 implementations; coverage reason category_decode_failed at 0x100000180: Unmapped or ambiguous metadata pointer 0x100005020; 3,025 bytes category kept (class_name: null, class_source: "unresolved", instance_methods: ["performAction:"]), 1 implementation; coverage reason category_class_unresolved at 0x100000208: Category FixtureCategory class reference 0x100005000: Unmapped or ambiguous metadata pointer 0x100005020; 4,415 bytes

No class name is inferred from the invalid reference.

Change and scope

  • src/native/AppleObjcCategories.ts: the local class name is resolved in its own try.
    • On failure, className stays null. The category record, its methods (attributed to the existing (CategoryName) placeholder owner, as for a zero reference), protocols and properties are still produced.
    • A category_class_unresolved issue, located at the cls field, records the original error message.
  • Categories bound to external classes and categories with readable local classes are unchanged.

Contract and boundary impact

  • Semantic owner and earliest changed stage: the Objective-C category decoder, at its per-record decode boundary.

  • Contribution scope fit and linked maintainer decision: a bug fix within the existing static, read-only boundary; not applicable.

  • CLI and MCP/tool-catalog contract: schemas unchanged.

  • Provider, bridge, target-format, or platform compatibility: the Apple metadata reader only.

  • Evidence, artifact, provenance, or reconstruction contract: partial facts are preserved with an explicit unknown owner and a meaningful reason.

  • Target selection, authority, upstream behavior, and cleanup details: not applicable.

  • Generated metadata, package, or installation impact: none.

  • Read existing files or captured data.

Evidence and regression coverage

  • Tests added or updated: src/native/AppleDispatchMetadata.test.ts adds an unmapped-class variant of the existing category fixture. The variant has an unmapped cls and a mapped implementation. The test asserts the category's unresolved identity, its method, its implementation at 0x100000700 attributed to (FixtureCategory), and partial category coverage with the category_class_unresolved reason at the cls field. It fails on main and passes with the fix.
  • Real applications, inspect-native-dispatch-metadata, main vs this PR, median of 5 runs:
binary categories main this PR
/Applications/XLD.app/Contents/MacOS/XLD 7 (external) 545 ms, 2,040,097 bytes, result 0f90d381… 543 ms, 2,040,097 bytes, result 0f90d381…
/System/Applications/Calculator.app/Contents/MacOS/Calculator 0 480 ms, 939,041 bytes, b454adf6… 480 ms, 939,041 bytes, b454adf6…

Output is byte-identical and timing is unchanged for real images whose category class references are readable.

  • Remaining proof gaps:
    • None of the probed real apps (TextEdit, Font Book, XLD, KeepingYouAwake, Transmission, foobar2000, Sublime Text) has a local-class category, so the changed localClassName path was exercised only by the fixtures.
    • No real image with an unmapped category class reference was available.

Validation performed

  • npx vitest run src/native/AppleDispatchMetadata.test.ts — 39 passed; against main, 1 failed as expected.
  • npx vitest run src/native tests/boundary/native tests/boundary/providers/native tests/boundary/cli/nativeDispatchPropertyAttributes.test.ts tests/boundary/filesystem/directAnalysisSnapshotReplay.test.ts — 52 files, 600 passed.
  • npm run check:fast — passed.
  • Real CLI runs on the issue's fixtures and the apps above.

Compatibility, safety, and release

  • Breaking changes or migration steps: none.
  • Real Hopper/Ghidra, browser, or OS coverage: macOS arm64 Apple metadata reader.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: static parsing only.

Author readiness

Human owner:

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • 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.

🤖 Generated with Claude Code


🔄 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/4093 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/15/2026 **Status:** ✅ Merged **Merged:** 10/15/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `fix/4012-objc-category-unresolved-class` --- ### 📝 Commits (1) - [`f67b5a3`](https://github.com/morluto/rea/commit/f67b5a3313d4f7981b028f88b942d2b8046f9d52) fix(native): keep a category whose class reference cannot be read ### 📊 Changes **2 files changed** (+54 additions, -5 deletions) <details> <summary>View changed files</summary> 📝 `src/native/AppleDispatchMetadata.test.ts` (+38 -3) 📝 `src/native/AppleObjcCategories.ts` (+16 -2) </details> ### 📄 Description ## Summary Fixes #4012. `inspect_native_dispatch_metadata` threw away a whole Objective-C category when its nonzero class reference pointed outside mapped metadata. The category's name, method selectors and implementations were readable and were lost with it. The category is now kept: its class identity is reported as unresolved, and category coverage is partial, with the reason. ## Problem and expected behavior `decodeObjcCategories` called `input.localClassName(local)` inside the category's single `try`. For an unmapped reference that call throws, so the record was replaced by a generic `category_decode_failed` issue. A zero class reference already produces the right shape (`class_name: null`, `class_source: "unresolved"`, decode `partial`), so the schema already supports this. Reproduced with the issue's generated arm64 fixtures through the built CLI. The two fixtures differ only in `category_t.cls`: | fixture | main | this PR | |---|---|---| | `cls = 0` (control) | category kept (unresolved), 1 implementation, coverage partial, 3,999 bytes | unchanged | | `cls = 0x100005000` (unmapped) | **no category, 0 implementations**; coverage reason `category_decode_failed at 0x100000180: Unmapped or ambiguous metadata pointer 0x100005020`; 3,025 bytes | **category kept** (`class_name: null`, `class_source: "unresolved"`, `instance_methods: ["performAction:"]`), 1 implementation; coverage reason `category_class_unresolved at 0x100000208: Category FixtureCategory class reference 0x100005000: Unmapped or ambiguous metadata pointer 0x100005020`; 4,415 bytes | No class name is inferred from the invalid reference. ## Change and scope - `src/native/AppleObjcCategories.ts`: the local class name is resolved in its own `try`. - On failure, `className` stays `null`. The category record, its methods (attributed to the existing `(CategoryName)` placeholder owner, as for a zero reference), protocols and properties are still produced. - A `category_class_unresolved` issue, located at the `cls` field, records the original error message. - Categories bound to external classes and categories with readable local classes are unchanged. ## Contract and boundary impact - Semantic owner and earliest changed stage: the Objective-C category decoder, at its per-record decode boundary. - Contribution scope fit and linked maintainer decision: a bug fix within the existing static, read-only boundary; not applicable. - CLI and MCP/tool-catalog contract: schemas unchanged. - Provider, bridge, target-format, or platform compatibility: the Apple metadata reader only. - Evidence, artifact, provenance, or reconstruction contract: partial facts are preserved with an explicit unknown owner and a meaningful reason. - Target selection, authority, upstream behavior, and cleanup details: not applicable. - Generated metadata, package, or installation impact: none. - [x] Read existing files or captured data. ## Evidence and regression coverage - Tests added or updated: `src/native/AppleDispatchMetadata.test.ts` adds an `unmapped-class` variant of the existing category fixture. The variant has an unmapped `cls` and a mapped implementation. The test asserts the category's unresolved identity, its method, its implementation at `0x100000700` attributed to `(FixtureCategory)`, and partial category coverage with the `category_class_unresolved` reason at the `cls` field. It fails on main and passes with the fix. - Real applications, `inspect-native-dispatch-metadata`, main vs this PR, median of 5 runs: | binary | categories | main | this PR | |---|---|---|---| | `/Applications/XLD.app/Contents/MacOS/XLD` | 7 (external) | 545 ms, 2,040,097 bytes, result `0f90d381…` | 543 ms, 2,040,097 bytes, result `0f90d381…` | | `/System/Applications/Calculator.app/Contents/MacOS/Calculator` | 0 | 480 ms, 939,041 bytes, `b454adf6…` | 480 ms, 939,041 bytes, `b454adf6…` | Output is byte-identical and timing is unchanged for real images whose category class references are readable. - Remaining proof gaps: - None of the probed real apps (TextEdit, Font Book, XLD, KeepingYouAwake, Transmission, foobar2000, Sublime Text) has a local-class category, so the changed `localClassName` path was exercised only by the fixtures. - No real image with an unmapped category class reference was available. ## Validation performed - `npx vitest run src/native/AppleDispatchMetadata.test.ts` — 39 passed; against main, 1 failed as expected. - `npx vitest run src/native tests/boundary/native tests/boundary/providers/native tests/boundary/cli/nativeDispatchPropertyAttributes.test.ts tests/boundary/filesystem/directAnalysisSnapshotReplay.test.ts` — 52 files, 600 passed. - `npm run check:fast` — passed. - Real CLI runs on the issue's fixtures and the apps above. ## Compatibility, safety, and release - Breaking changes or migration steps: none. - Real Hopper/Ghidra, browser, or OS coverage: macOS arm64 Apple metadata reader. - Package or release metadata impact: none. - Security, privacy, process, or containment review: static parsing only. ## Author readiness Human owner: <!-- @GitHub-handle --> - [ ] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [ ] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [ ] I declare this PR ready for initial maintainer review. ## Before merge - [ ] This PR addresses a concrete problem or an agreed enhancement. - [ ] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [ ] 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. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:11: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#6051
No description provided.