[GH-ISSUE #1765] [Bug] inspect-artifact /bin/ls still fails on macOS 27: rea names the CPU_SUBTYPE_ARM64E_X1 slice arm64 #592

Closed
opened 2026-10-15 18:26:28 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @dhl84 on GitHub (Oct 11, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/1765

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

On main at 062723e4, rea inspect-artifact /bin/ls --json still fails with integrity_mismatch on macOS 27.0.1. This is the failure from #1168. The boundary test tests/boundary/providers/native/machoSliceReader.test.ts fails with the same detail:

lipo slice metadata disagrees with the Mach-O FAT table: arm64e.x1 (cputype=CPU_TYPE_ARM64, cpusubtype=unknown arm64 cpusubtype, offset=163840, size=88672, alignment=16384)

The fix for #1168 accepts the lipo name arm64e.<variant> when rea names the FAT slice arm64e. The third slice of /bin/ls does not use subtype 2. Its FAT entry has cputype 0x0100000c and cpusubtype 0x8000000c.

The SDK header mach/machine.h defines subtype 12 as CPU_SUBTYPE_ARM64E_X1. Its macro CPU_SUBTYPE_HAS_ARM64E puts subtype 12 in the arm64e family. architectureName in src/artifacts/apple/MachoLoadCommandReader.ts knows only subtype 2, so it names this slice arm64, and lipoNameMatches rejects the match. The arm64e.x1 fixture in artifactProvider.machOSlices.test.ts uses subtype 2 (0x81000002), so the unit tests did not find the problem.

The same full test run found two more failures. Both come from the state of the test host:

  1. nativeDmgArtifactReader.test.ts > "classifies a real hdiutil verify refusal as a format failure with captured output" gets unavailable in place of format. hdiutil follows the AppleLanguages setting. With en-GB it writes hdiutil: verify failed - image not recognised, and verifyFailureReason matches only the US spelling. LANG=en_US.UTF-8 does not change the output, and hdiutil verify -plist gives no structured error.
  2. processCaptureLifecycle.test.ts > "samples and cleans a source-owned child and grandchild process tree" fails with RangeError: stdout maxBuffer length exceeded. The test runs ps -axo command= with the Node default maxBuffer of 1 MiB. On a host with 1905 processes, this command writes 1.52 MB.

Reproduction

sw_vers -productVersion       # 27.0.1
lipo -detailed_info /bin/ls   # third slice: arm64e.x1, "unknown arm64 cpusubtype"
xxd -s 0x30 -l 8 /bin/ls      # 0100 000c 8000 000c
npm ci && npm run build:cached
node scripts/rea.mjs inspect-artifact /bin/ls --json; echo "exit=$?"
defaults read -g AppleLanguages   # ("en-GB", ...)
printf 'not a disk image\n' > invalid.dmg
/usr/bin/hdiutil verify invalid.dmg

Expected behavior

inspect-artifact /bin/ls succeeds on macOS 27. The three tests pass on a macOS 27 host that uses an en-GB locale and runs many processes.

Proposed fix

A local patch with the changes below makes the three tests pass. With the patch, inspect-artifact /bin/ls --json returns evidence and exits with code 0. npm run check:fast and npm run test:fast (4269 tests) also pass.

--- a/src/artifacts/apple/MachoLoadCommandReader.ts
+++ b/src/artifacts/apple/MachoLoadCommandReader.ts
@@ -521,2 +521,3 @@ const CPU_SUBTYPE_MASK = 0xff000000;
 const CPU_SUBTYPE_ARM64E = 2;
+const CPU_SUBTYPE_ARM64E_X1 = 12;
 const CPU_SUBTYPE_X86_64_H = 8;
@@ -526,3 +527,6 @@ const architectureName = (cpuType: number, cpuSubtype: number): string => {
   if (cpuType === (CPU_TYPE_ARM | CPU_ARCH_ABI64))
-    return subtype === CPU_SUBTYPE_ARM64E ? "arm64e" : "arm64";
+    // Matches the SDK's CPU_SUBTYPE_HAS_ARM64E: both PAC slices are arm64e.
+    return subtype === CPU_SUBTYPE_ARM64E || subtype === CPU_SUBTYPE_ARM64E_X1
+      ? "arm64e"
+      : "arm64";
--- a/src/artifacts/NativeDmgArtifactReader.ts
+++ b/src/artifacts/NativeDmgArtifactReader.ts
@@ -574,3 +574,5 @@ const verifyFailureReason = (
   switch (diagnostic) {
+    // hdiutil follows AppleLanguages, so en-GB and en-AU spell it "recognised".
     case "image not recognized":
+    case "image not recognised":
       return "format";
--- a/tests/boundary/process/processCaptureLifecycle.test.ts
+++ b/tests/boundary/process/processCaptureLifecycle.test.ts
@@ -1071,3 +1071,6 @@ itWithCaptureCapability(
-    const { stdout } = await execFileAsync("ps", ["-axo", "command="]);
+    // A busy host's full process table exceeds Node's 1 MiB default buffer.
+    const { stdout } = await execFileAsync("ps", ["-axo", "command="], {
+      maxBuffer: Number.POSITIVE_INFINITY,
+    });

The patch also changes two tests. The arm64e.x1 fixture uses the real subtype 0x8000000c, and it fails before the source change. The fake-output DMG test checks both spellings.

I also saw failures in processCaptureProgress.test.ts and processFilesystemCoverageAdapters.test.ts with cleanup_incomplete and environment_unavailable. The failing test changed from run to run, and the host had a load average of 42 to 52 on 16 cores at that time. I did not find a cause, so this issue does not include them.

Impact and scope

On macOS 27, artifact inspection fails for system universal binaries such as /bin/ls. On a host with a non-US English locale, the DMG reader reports unavailable for a file that is not a disk image. The ps problem affects only the test.

REA version

6.4.0, main at 062723e4

Runtime and platform

macOS 27.0.1 (26A434), arm64, Node 24.18.0, npm 11.16.0

Target and artifact context

/bin/ls from macOS 27.0.1, and a text file named invalid.dmg

Interface

CLI

Originally created by @dhl84 on GitHub (Oct 11, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/1765 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior On `main` at 062723e4, `rea inspect-artifact /bin/ls --json` still fails with `integrity_mismatch` on macOS 27.0.1. This is the failure from #1168. The boundary test `tests/boundary/providers/native/machoSliceReader.test.ts` fails with the same detail: ```text lipo slice metadata disagrees with the Mach-O FAT table: arm64e.x1 (cputype=CPU_TYPE_ARM64, cpusubtype=unknown arm64 cpusubtype, offset=163840, size=88672, alignment=16384) ``` The fix for #1168 accepts the `lipo` name `arm64e.<variant>` when rea names the FAT slice `arm64e`. The third slice of `/bin/ls` does not use subtype 2. Its FAT entry has `cputype 0x0100000c` and `cpusubtype 0x8000000c`. The SDK header `mach/machine.h` defines subtype 12 as `CPU_SUBTYPE_ARM64E_X1`. Its macro `CPU_SUBTYPE_HAS_ARM64E` puts subtype 12 in the arm64e family. `architectureName` in `src/artifacts/apple/MachoLoadCommandReader.ts` knows only subtype 2, so it names this slice `arm64`, and `lipoNameMatches` rejects the match. The `arm64e.x1` fixture in `artifactProvider.machOSlices.test.ts` uses subtype 2 (`0x81000002`), so the unit tests did not find the problem. The same full test run found two more failures. Both come from the state of the test host: 1. `nativeDmgArtifactReader.test.ts` > "classifies a real hdiutil verify refusal as a format failure with captured output" gets `unavailable` in place of `format`. `hdiutil` follows the `AppleLanguages` setting. With `en-GB` it writes `hdiutil: verify failed - image not recognised`, and `verifyFailureReason` matches only the US spelling. `LANG=en_US.UTF-8` does not change the output, and `hdiutil verify -plist` gives no structured error. 2. `processCaptureLifecycle.test.ts` > "samples and cleans a source-owned child and grandchild process tree" fails with `RangeError: stdout maxBuffer length exceeded`. The test runs `ps -axo command=` with the Node default `maxBuffer` of 1 MiB. On a host with 1905 processes, this command writes 1.52 MB. ### Reproduction ```sh sw_vers -productVersion # 27.0.1 lipo -detailed_info /bin/ls # third slice: arm64e.x1, "unknown arm64 cpusubtype" xxd -s 0x30 -l 8 /bin/ls # 0100 000c 8000 000c npm ci && npm run build:cached node scripts/rea.mjs inspect-artifact /bin/ls --json; echo "exit=$?" ``` ```sh defaults read -g AppleLanguages # ("en-GB", ...) printf 'not a disk image\n' > invalid.dmg /usr/bin/hdiutil verify invalid.dmg ``` ### Expected behavior `inspect-artifact /bin/ls` succeeds on macOS 27. The three tests pass on a macOS 27 host that uses an en-GB locale and runs many processes. ### Proposed fix A local patch with the changes below makes the three tests pass. With the patch, `inspect-artifact /bin/ls --json` returns evidence and exits with code 0. `npm run check:fast` and `npm run test:fast` (4269 tests) also pass. ```diff --- a/src/artifacts/apple/MachoLoadCommandReader.ts +++ b/src/artifacts/apple/MachoLoadCommandReader.ts @@ -521,2 +521,3 @@ const CPU_SUBTYPE_MASK = 0xff000000; const CPU_SUBTYPE_ARM64E = 2; +const CPU_SUBTYPE_ARM64E_X1 = 12; const CPU_SUBTYPE_X86_64_H = 8; @@ -526,3 +527,6 @@ const architectureName = (cpuType: number, cpuSubtype: number): string => { if (cpuType === (CPU_TYPE_ARM | CPU_ARCH_ABI64)) - return subtype === CPU_SUBTYPE_ARM64E ? "arm64e" : "arm64"; + // Matches the SDK's CPU_SUBTYPE_HAS_ARM64E: both PAC slices are arm64e. + return subtype === CPU_SUBTYPE_ARM64E || subtype === CPU_SUBTYPE_ARM64E_X1 + ? "arm64e" + : "arm64"; --- a/src/artifacts/NativeDmgArtifactReader.ts +++ b/src/artifacts/NativeDmgArtifactReader.ts @@ -574,3 +574,5 @@ const verifyFailureReason = ( switch (diagnostic) { + // hdiutil follows AppleLanguages, so en-GB and en-AU spell it "recognised". case "image not recognized": + case "image not recognised": return "format"; --- a/tests/boundary/process/processCaptureLifecycle.test.ts +++ b/tests/boundary/process/processCaptureLifecycle.test.ts @@ -1071,3 +1071,6 @@ itWithCaptureCapability( - const { stdout } = await execFileAsync("ps", ["-axo", "command="]); + // A busy host's full process table exceeds Node's 1 MiB default buffer. + const { stdout } = await execFileAsync("ps", ["-axo", "command="], { + maxBuffer: Number.POSITIVE_INFINITY, + }); ``` The patch also changes two tests. The `arm64e.x1` fixture uses the real subtype `0x8000000c`, and it fails before the source change. The fake-output DMG test checks both spellings. I also saw failures in `processCaptureProgress.test.ts` and `processFilesystemCoverageAdapters.test.ts` with `cleanup_incomplete` and `environment_unavailable`. The failing test changed from run to run, and the host had a load average of 42 to 52 on 16 cores at that time. I did not find a cause, so this issue does not include them. ### Impact and scope On macOS 27, artifact inspection fails for system universal binaries such as `/bin/ls`. On a host with a non-US English locale, the DMG reader reports `unavailable` for a file that is not a disk image. The `ps` problem affects only the test. ### REA version 6.4.0, `main` at 062723e4 ### Runtime and platform macOS 27.0.1 (26A434), arm64, Node 24.18.0, npm 11.16.0 ### Target and artifact context `/bin/ls` from macOS 27.0.1, and a text file named `invalid.dmg` ### Interface CLI
bsakaguchi 2026-10-15 18:26:28 +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#592
No description provided.