ReviewOS

zig-utils/zig-js

JIT: fix x86-64 executable-memory return fixture

#627
Closed chris opened this 11 days ago ·
11 days ago

Parents: #483, #484, #485 Related: #626, #493

Problem

Current Zig dev.1818 allows the Linux x86-64 executable-memory fixture to reach generated-code execution, where it deterministically segfaults. The byte sequence documented as mov eax, 42; ret contains an extra zero byte between the 32-bit immediate and ret: b8 2a 00 00 00 00 c3. x86 decodes the trailing 00 c3 as another instruction rather than ret, so execution falls beyond the emitted body. CI run 32338430544 reproduces the crash at address 0x2a.

Scope

  • Encode the exact six-byte mov eax, imm32; ret sequence.
  • Preserve the RW -> RX publication boundary and immutable-after-publication contract.
  • Validate the fixture on x86_64 Linux under the current Zig toolchain and retain the AArch64 control.

No-workaround rules

  • No skipping Linux/x86-64, disabling executable-memory tests, catching the signal, padding into a coincidental return, or weakening W^X.

Acceptance

  • The exact dev.1818 x86_64 Linux fixture returns 42 without a signal.
  • Executable-memory/W^X focused tests and full units pass.
  • CI advances beyond the generated-code fixture; no Test262 behavior change is claimed.

Security boundary

Generated bytes are an executable control-flow boundary. Instruction encodings and used lengths must be exact; falling through into padding or adjacent memory is never acceptable.

11 days ago

Landed in 6ca1774b: the x86-64 fixture is now the exact six-byte mov eax, 42; ret sequence. Exact dev.1818 and repository-compiler focused tests pass (1/1 each), the dev.1818 x86_64-linux-gnu artifact links, the full local suite passes 1,738 with 1 skip and zero failures/leaks, and dependency-audit is green. The fresh main CI run is the authoritative Linux x86-64 execution check.

11 days ago

Authoritative Linux x86-64 execution is now green: main CI run 32339438292, unit shard 0 ran jit.test.CodeMemory publishes and executes native code successfully (OK, 0 ms). The shard later remained red only for the separately tracked Annex B heap-limit failure #628.

11 days ago

Reopened: the uncancelled Linux executable-memory-wx gate found a second standalone copy of the old seven-byte x86 fixture in tests/executable_memory_wx.zig. Its bytes are b8 2a 00 00 00 00 c3; after the five-byte mov eax, 42, the extra 00 begins add byte ptr [rax], al at address 42, so the published-execution child faults and the parent reports TestPublishedExecutionFailed. The production CodeMemory test fixed in 6ca1774b passed on Linux; I am applying the same exact six-byte encoding to this separate W^X process fixture.

11 days ago

Follow-up landed in a55eae9a.

The standalone W^X process fixture now uses the exact six-byte x86-64 sequence and compile-time asserts both supported architecture lengths. Exact Zig dev.1818 passes the gate in Debug and ReleaseSafe on macOS/aarch64; the new Linux x86-64 run will provide the branch-execution proof.

11 days ago

Fresh Linux x86-64 validation passes the corrected standalone W^X fixture in both configured build modes: executable-memory-wx. This confirms a55eae9a executes the exact six-byte x86-64 function without the former stray memory-write opcode.

Sign in to comment on this issue.