Skip to content

fix(native): retain Objective-C classes whose adopted-protocol list exceeds its count limit - #8958

Open
SahinurDEV wants to merge 1 commit into
morluto:mainfrom
SahinurDEV:fix/objc-protocol-list-limit
Open

SahinurDEV wants to merge 1 commit into
morluto:mainfrom
SahinurDEV:fix/objc-protocol-list-limit

Conversation

@SahinurDEV

Copy link
Copy Markdown

Summary

Fixes #8945.

inspect-native-dispatch-metadata dropped a class's objc_classes row (and never visited its metaclass) when the class's adopted-protocol list declared more than 20000 entries. The count guard in the protocol reader throws before the class row is appended, so the outer class-list catch only recorded the reason. Method implementations and ivars survived because they are appended earlier.

After this change the class and its metaclass are retained, the class row is marked partial with protocol_list_unreadable, its protocols is empty, and the class coverage stays partial with the original limit reason.

Problem and expected behavior

  • Trigger: a class_ro_t base protocol list whose count is above 20000.
  • Violated invariant: AGENTS.md asks to keep independently readable partial facts with a meaningful failure reason. Property-list failures already work this way.
  • Expected: keep the class and metaclass, do not present the protocol list as fully decoded, and keep the existing count bound so no oversized traversal happens.

Change and scope

readClass now reads the adopted-protocol list through a small readAdoptedProtocols helper. When the list read throws, the helper records Protocol list of <class>: <reason> in the class failures and returns an empty list. The class row then gets protocol_list_unreadable in its decode reasons, the same way max_records_reached and superclass_binding_unresolved are reported.

Not included: the 20000 limit is unchanged, category protocol lists (decodeObjcCategories) keep their current behavior, and no new schema fields are added (decode reason is already a free-form string).

Contribution scope: an ordinary fix inside the existing static Mach-O reader; maintainer scope decision not applicable.

Contract and boundary impact

  • Semantic owner and earliest changed stage: decodeObjcDispatchFacets (src/native/AppleObjcDispatchFacets.ts), the class row producer for inspect_native_dispatch_metadata.
  • Contribution scope fit and linked maintainer decision: not applicable (bug fix in existing boundary).
  • CLI and MCP/tool-catalog contract: same schema. Affected inputs now return class/metaclass rows plus a partial reason instead of no rows.
  • Provider, bridge, target-format, or platform compatibility: none.
  • Evidence, artifact, provenance, or reconstruction contract: more retained facts; coverage stays partial.
  • Target selection, authority, upstream behavior, and cleanup details (if applicable): not applicable.
  • Generated metadata (docs/public/product-catalog.json), package, or installation impact: none.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

  • Tests added or updated: src/native/AppleDispatchMetadata.test.ts, new Objective-C adopted protocol-list count limit block, built on the same fixture changes as the issue's reproduction (root class, count at 0x700):

    • count 20001 keeps both rows (class partial / protocol_list_unreadable, metaclass decoded), the three class properties, the ivar and the performAction: implementation, and coverage is partial with Protocol list of Fixture: Protocol list exceeds 20000 entries.
    • counts 0 and 1 keep complete class coverage and no protocol_list_unreadable reason.
  • Base reproduction or other evidence: executed. With the source change stashed, the new count-20001 test fails (no class rows); with it applied, it passes.

  • User-visible CLI/MCP output (if applicable): for the issue's oversized fixture, objc_classes is now [{name: "Fixture", is_meta_class: false, decode: partial}, {name: "Fixture", is_meta_class: true, decode: decoded}] and objc_class_method_ivar_metadata coverage is partial, examined: 2, decoded: 1 (derived from the unit test, which calls the same decoder the CLI uses).

  • Remaining proof gaps: not run through the compiled CLI or on macOS; no real-world binaries with this layout were tested.

  • 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/native/AppleDispatchMetadata.test.ts src/native/AppleDispatchMetadata.failure.test.ts src/native/AppleObjcClassCoverage.test.ts src/native/AppleObjcClassImportBindings.test.ts — 4 files, 132 tests passed
  • npx vitest run src/native — 53 files, 1163 passed, 1 skipped
  • npm run typecheck — passed
  • npm run lint — passed (no new errors); npx oxlint on the changed source keeps the existing max-lines-per-function/complexity warnings on readClass (the try/catch lives in a separate helper)
  • npx oxfmt --check on the changed files — passed
  • npm run verify:module-boundaries — passed

Compatibility, safety, and release

  • Breaking changes or migration steps: none.
  • Real Hopper/Ghidra, browser, or OS coverage: Linux only; this static reader needs no external provider.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: no extra reads; the count guard still stops before traversing the oversized list.

Author readiness

Human owner: @SahinurDEV

  • 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.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-11-05T04:10:00.924505Z
We couldn’t complete this review. Comment @codex review to try again.
1e602c8 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@greptile-apps

greptile-apps Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The change affects static Objective-C metadata results for binaries with oversized adopted-protocol lists.

The behavior fix appears sound, but the new helper must follow the repository’s required error shape before merging.

Findings

  1. P2 Failure uses two separate signals ▶
Fix with agent prompt
### Issue 1
src/native/AppleObjcDispatchFacets.ts:286-293
`readAdoptedProtocols` reports a failed read through an `unreadable` boolean and a shared error list. This violates the repository directive to model expected failures with the tagged error algebra and `Result`.

Return `Result<string[], ...>` with a tagged error, then let `readClass` record the reason and mark the row partial. This repository requirement must be satisfied before merging.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

Retains Objective-C class and metaclass rows when an adopted-protocol list cannot be read.

  • Objective-C classes remain visible when their protocol lists exceed the reader limit.

No security issue was established. Supersession could not be checked remotely because GitHub access was unavailable. No tests were run during this review.

SahinurDEV explicitly excludes category protocol-list recovery from this PR’s scope.

Reviews (1) · Last reviewed commit: "fix(native): retain Objective-C classes ..." · Reviewed by Greptile

Comment on lines +286 to +293
): { protocols: string[]; unreadable: boolean } => {
try {
return { protocols: list(), unreadable: false };
} catch (cause: unknown) {
failures.push(
`Protocol list of ${owner}: ${cause instanceof Error ? cause.message : String(cause)}`,
);
return { protocols: [], unreadable: true };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Failure uses two separate signals

readAdoptedProtocols reports a failed read through an unreadable boolean and a shared error list. This violates the repository directive to model expected failures with the tagged error algebra and Result.

Return Result<string[], ...> with a tagged error, then let readClass record the reason and mark the row partial. This repository requirement must be satisfied before merging.

Context Used: AGENTS.md (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/native/AppleObjcDispatchFacets.ts
Line: 286-293

Comment:
**Failure uses two separate signals**

`readAdoptedProtocols` reports a failed read through an `unreadable` boolean and a shared error list. This violates the repository directive to model expected failures with the tagged error algebra and `Result`.

Return `Result<string[], ...>` with a tagged error, then let `readClass` record the reason and mark the row partial. This repository requirement must be satisfied before merging.

**Context Used:** AGENTS.md ([source](https://github.com/morluto/rea/blob/main/AGENTS.md))

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] inspect-native-dispatch-metadata drops class and metaclass rows when an adopted-protocol list exceeds its count limit

1 participant