[PR #1982] [MERGED] fix(native): accept universal binaries with LIB64 x86_64 slices #4948

Closed
opened 2026-10-31 00:57:16 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

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

Base: main ← Head: fix/native-lipo-capability-bits


📝 Commits (7)

  • 18feae5 fix(native): apply printed lipo capability bits to CPU subtypes
  • ae9ca74 fix(native): leave lipo CPU subtypes unknown without capability bits
  • 1f90a38 test(native): cover printed and blank lipo capability bits
  • d2c38b5 test(native): match a LIB64 x86_64 slice with blank lipo capabilities
  • 0e586a6 fix(native): compare named lipo subtype bits without capability bytes
  • df357a8 test(native): share LIB64 slice reader setup
  • 951bec1 test(native): reject a blank-capability lipo subtype naming other bits

📊 Changes

4 files changed (+121 additions, -4 deletions)

View changed files

📝 src/artifacts/MachOSliceArtifactReader.ts (+16 -2)
📝 src/native/parsers/lipo.test.ts (+27 -0)
📝 src/native/parsers/lipo.ts (+20 -2)
📝 tests/boundary/providers/native/artifactProvider.machOSlices.test.ts (+58 -0)

📄 Description

Summary

Universal Mach-O files whose x86_64 slice carries the LIB64 capability bit (FAT cpusubtype 0x80000003, common for x86_64 executables) fail slice reading with lipo slice metadata disagrees with the Mach-O FAT table: x86_64 .... The lipo parser applied capability bits only to arm64e, so it reported subtype 3 for these slices. Apply the capability byte lipo prints, and leave the subtype code unknown when lipo prints none.

No existing issue covers this. #1168 and #1765 concern arm64e slices, and open #1772 does not touch the lipo parser.

Problem and expected behavior

On macOS 26.7.1, lipo -detailed_info from Xcode prints this for /Applications/Sublime Text.app/Contents/MacOS/sublime_text:

architecture x86_64
    cputype CPU_TYPE_X86_64
    cpusubtype CPU_SUBTYPE_X86_ALL
    capabilities 
    offset 16384
    size 13873872
    align 2^14 (16384)

otool -f reports cpusubtype 3 and capabilities 0x80 for the same FAT entry. The same lipo prints the same blank line for /bin/ls, whose x86_64 capability byte is 0x0, so the blank line does not identify the subtype. cctools lipo prints capabilities CPU_SUBTYPE_LIB64 for this case instead (misc/lipo.c), which the parser also ignored.

In both cases cpuSubtypeCode returned 3. lipoMatchesSlice compares that with the FAT subtype 0x80000003, finds no matching slice, and MachOSliceArtifactReader throws an integrity failure, the same failure class #1765 shows surfacing as integrity_mismatch. Expected: both slices are listed, as for universal files whose x86_64 entry has no capability bits.

Change and scope

  • capabilityBits reads the capability byte lipo prints next to the subtype: CPU_SUBTYPE_LIB64 (0x80) or a hex byte such as 0x80 or 0x0. Non-arm64e subtype codes include it, as arm64e codes already include their pointer-auth byte.
  • When lipo prints no capability byte, the subtype code is null, the rule arm64e already follows without PTR_AUTH_VERSION, and the entry keeps the existing "retained as unnormalized source text" limitation.
  • Slice matching still compares what the record does name: with a null code, lipoSubtypeMatches compares the subtype bits from lipoSubtypeBits with the FAT entry's low 24 bits, so a record naming another subtype (for example CPU_SUBTYPE_ARM64_ALL for an ARM64_V8 entry) is still rejected.
  • Not included: inspect_macho slice selection within one CPU family, which is a separate problem.

Contract and boundary impact

  • Semantic owner and earliest changed stage: lipo -detailed_info parsing in src/native/parsers/lipo.ts, and its slice comparison in src/artifacts/MachOSliceArtifactReader.ts.
  • CLI and MCP/tool-catalog contract: schemas unchanged. cpu_subtype_code includes printed capability bits and is null when lipo prints none.
  • Provider, bridge, target-format, or platform compatibility: macOS lipo output with named, hex or blank capabilities.
  • Evidence, artifact, provenance, or reconstruction contract: affected universal files yield slice entries instead of an integrity failure; a slice whose capabilities line is blank carries the existing unnormalized-subtype limitation.
  • Process execution, authorization, cleanup, or containment impact: none.
  • Generated metadata (docs/public/product-catalog.json), package, or installation impact: none.

Evidence and regression coverage

  • Tests added or updated: src/native/parsers/lipo.test.ts covers CPU_SUBTYPE_LIB64, 0x80, 0x0 and the blank line. tests/boundary/providers/native/artifactProvider.machOSlices.test.ts reads a FAT image whose x86_64 entry carries 0x80000003 with the macOS 26 lipo output and expects both slices (on the base revision that read throws the integrity failure), and still rejects a blank-capability record naming CPU_SUBTYPE_X86_64_H for that entry.
  • Base reproduction or other evidence: the lipo -detailed_info and otool -f output above, observed on macOS 26.7.1 for Sublime Text and /bin/ls, and cctools misc/lipo.c for the named LIB64 form. The failure path through cpuSubtypeCode and lipoMatchesSlice is source-derived.
  • User-visible CLI/MCP output (if applicable): before, lipo slice metadata disagrees with the Mach-O FAT table: x86_64 (cputype=CPU_TYPE_X86_64, cpusubtype=CPU_SUBTYPE_X86_ALL, offset=16384, ...); after, the x86_64 and arm64 slices.
  • Remaining proof gaps: REA itself was not run against the affected applications; the evidence is the producer output above plus source reading.

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

  • No project commands were run locally: dependencies are not installed. Only the system lipo -detailed_info and otool -f were run on the binaries named above.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. cpu_subtype_code changes from an assumed value to null only where lipo prints no capability byte.
  • Real Hopper/Ghidra, browser, or OS coverage: producer output observed on macOS 26.7.1; no REA lane was run.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: none; slice ranges are still checked against the structural FAT index.

Review checklist

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

🔄 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/1982 **Author:** [@viniciusdsandrade](https://github.com/viniciusdsandrade) **Created:** 10/11/2026 **Status:** ✅ Merged **Merged:** 10/12/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `fix/native-lipo-capability-bits` --- ### 📝 Commits (7) - [`18feae5`](https://github.com/morluto/rea/commit/18feae520a99a8d6269842709698362e3859e151) fix(native): apply printed lipo capability bits to CPU subtypes - [`ae9ca74`](https://github.com/morluto/rea/commit/ae9ca74333f5e5ff9a3ca78da8b16eadae8c0387) fix(native): leave lipo CPU subtypes unknown without capability bits - [`1f90a38`](https://github.com/morluto/rea/commit/1f90a38c97e87f38cb5f03d75c442bbbc1fda567) test(native): cover printed and blank lipo capability bits - [`d2c38b5`](https://github.com/morluto/rea/commit/d2c38b5f06865316f355826898dd845b755bcfb8) test(native): match a LIB64 x86_64 slice with blank lipo capabilities - [`0e586a6`](https://github.com/morluto/rea/commit/0e586a63b80f71ba439c8c2843bf5a14e6e88c50) fix(native): compare named lipo subtype bits without capability bytes - [`df357a8`](https://github.com/morluto/rea/commit/df357a8376c12a4c8737ff528fee79daf04eacbf) test(native): share LIB64 slice reader setup - [`951bec1`](https://github.com/morluto/rea/commit/951bec1322ba26d7962ac82d1e66e04d7362d2c2) test(native): reject a blank-capability lipo subtype naming other bits ### 📊 Changes **4 files changed** (+121 additions, -4 deletions) <details> <summary>View changed files</summary> 📝 `src/artifacts/MachOSliceArtifactReader.ts` (+16 -2) 📝 `src/native/parsers/lipo.test.ts` (+27 -0) 📝 `src/native/parsers/lipo.ts` (+20 -2) 📝 `tests/boundary/providers/native/artifactProvider.machOSlices.test.ts` (+58 -0) </details> ### 📄 Description ## Summary Universal Mach-O files whose x86_64 slice carries the LIB64 capability bit (FAT cpusubtype `0x80000003`, common for x86_64 executables) fail slice reading with `lipo slice metadata disagrees with the Mach-O FAT table: x86_64 ...`. The lipo parser applied capability bits only to arm64e, so it reported subtype 3 for these slices. Apply the capability byte lipo prints, and leave the subtype code unknown when lipo prints none. No existing issue covers this. #1168 and #1765 concern arm64e slices, and open #1772 does not touch the lipo parser. ## Problem and expected behavior On macOS 26.7.1, `lipo -detailed_info` from Xcode prints this for `/Applications/Sublime Text.app/Contents/MacOS/sublime_text`: ```text architecture x86_64 cputype CPU_TYPE_X86_64 cpusubtype CPU_SUBTYPE_X86_ALL capabilities offset 16384 size 13873872 align 2^14 (16384) ``` `otool -f` reports `cpusubtype 3` and `capabilities 0x80` for the same FAT entry. The same lipo prints the same blank line for `/bin/ls`, whose x86_64 capability byte is `0x0`, so the blank line does not identify the subtype. cctools lipo prints `capabilities CPU_SUBTYPE_LIB64` for this case instead (`misc/lipo.c`), which the parser also ignored. In both cases `cpuSubtypeCode` returned 3. `lipoMatchesSlice` compares that with the FAT subtype `0x80000003`, finds no matching slice, and `MachOSliceArtifactReader` throws an `integrity` failure, the same failure class #1765 shows surfacing as `integrity_mismatch`. Expected: both slices are listed, as for universal files whose x86_64 entry has no capability bits. ## Change and scope - `capabilityBits` reads the capability byte lipo prints next to the subtype: `CPU_SUBTYPE_LIB64` (`0x80`) or a hex byte such as `0x80` or `0x0`. Non-arm64e subtype codes include it, as arm64e codes already include their pointer-auth byte. - When lipo prints no capability byte, the subtype code is `null`, the rule arm64e already follows without `PTR_AUTH_VERSION`, and the entry keeps the existing "retained as unnormalized source text" limitation. - Slice matching still compares what the record does name: with a `null` code, `lipoSubtypeMatches` compares the subtype bits from `lipoSubtypeBits` with the FAT entry's low 24 bits, so a record naming another subtype (for example `CPU_SUBTYPE_ARM64_ALL` for an `ARM64_V8` entry) is still rejected. - Not included: `inspect_macho` slice selection within one CPU family, which is a separate problem. ## Contract and boundary impact - Semantic owner and earliest changed stage: `lipo -detailed_info` parsing in `src/native/parsers/lipo.ts`, and its slice comparison in `src/artifacts/MachOSliceArtifactReader.ts`. - CLI and MCP/tool-catalog contract: schemas unchanged. `cpu_subtype_code` includes printed capability bits and is `null` when lipo prints none. - Provider, bridge, target-format, or platform compatibility: macOS lipo output with named, hex or blank capabilities. - Evidence, artifact, provenance, or reconstruction contract: affected universal files yield slice entries instead of an integrity failure; a slice whose capabilities line is blank carries the existing unnormalized-subtype limitation. - Process execution, authorization, cleanup, or containment impact: none. - Generated metadata (`docs/public/product-catalog.json`), package, or installation impact: none. ## Evidence and regression coverage - Tests added or updated: `src/native/parsers/lipo.test.ts` covers `CPU_SUBTYPE_LIB64`, `0x80`, `0x0` and the blank line. `tests/boundary/providers/native/artifactProvider.machOSlices.test.ts` reads a FAT image whose x86_64 entry carries `0x80000003` with the macOS 26 lipo output and expects both slices (on the base revision that read throws the integrity failure), and still rejects a blank-capability record naming `CPU_SUBTYPE_X86_64_H` for that entry. - Base reproduction or other evidence: the `lipo -detailed_info` and `otool -f` output above, observed on macOS 26.7.1 for Sublime Text and `/bin/ls`, and cctools `misc/lipo.c` for the named LIB64 form. The failure path through `cpuSubtypeCode` and `lipoMatchesSlice` is source-derived. - User-visible CLI/MCP output (if applicable): before, `lipo slice metadata disagrees with the Mach-O FAT table: x86_64 (cputype=CPU_TYPE_X86_64, cpusubtype=CPU_SUBTYPE_X86_ALL, offset=16384, ...)`; after, the x86_64 and arm64 slices. - Remaining proof gaps: REA itself was not run against the affected applications; the evidence is the producer output above plus source reading. 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 - No project commands were run locally: dependencies are not installed. Only the system `lipo -detailed_info` and `otool -f` were run on the binaries named above. ## Compatibility, safety, and release - Breaking changes or migration steps: none. `cpu_subtype_code` changes from an assumed value to `null` only where lipo prints no capability byte. - Real Hopper/Ghidra, browser, or OS coverage: producer output observed on macOS 26.7.1; no REA lane was run. - Package or release metadata impact: none. - Security, privacy, process, or containment review: none; slice ranges are still checked against the structural FAT index. ## Review checklist - [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] 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. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 00:57:16 +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#4948
No description provided.