Skip to content

Fix opcode table over-read crash on Windows#8

Open
tbdye wants to merge 1 commit into
cnvogelg:mainfrom
tbdye:fix-opcode-table-overread
Open

Fix opcode table over-read crash on Windows#8
tbdye wants to merge 1 commit into
cnvogelg:mainfrom
tbdye:fix-opcode-table-overread

Conversation

@tbdye

@tbdye tbdye commented Apr 7, 2026

Copy link
Copy Markdown

Problem

machine68k.CPU() crashes with ACCESS_VIOLATION on Windows. The segfault occurs during m68k_init()m68ki_build_opcode_table(), before any user code runs.

Root cause

The opcode handler table is terminated by a zero sentinel {0, 0, 0, {0,0,0,0,0}}. The first while loop in m68ki_build_opcode_table() scans forward looking for mask == 0xff00 as a phase transition:

while(ostruct->mask != 0xff00)

However, m68kmake never generates entries with mask 0xff00. The loop processes all ~1967 valid entries, reaches the zero terminator, evaluates 0 != 0xff00 as true, and continues reading past the end of the array.

On Linux/macOS this happens to work — the over-read lands in zero-filled BSS, and the subsequent == loops (mask == 0xf1f8, mask == 0xfff0, etc.) all exit immediately on mask=0, so the function completes despite the undefined behavior. On Windows, the .rdata section layout places the const array near a page boundary, and the over-read crosses into unmapped memory.

The subsequent loops are safe because they use == checks, which naturally terminate when they encounter a different or zero mask value. Only the first loop, which scans forward with !=, has this problem.

Fix

Add a zero-terminator guard to the first loop so it stops at the end of the table:

while(ostruct->mask != 0xff00 && ostruct->mask != 0)

Verification

  • CPU(1) no longer segfaults on Windows (tested Python 3.13 and 3.14)
  • Machine(1, 1024) works correctly
  • 41 tests pass, 34 skipped (pre-existing [remote]/[greenlet] skip conditions)

m68ki_build_opcode_table() scans past the end of the handler table
because the first while loop expects mask 0xff00 as a sentinel, but
m68kmake never generates entries with that mask. Add a zero-terminator
guard so the loop stops at the end of the table.

On Linux/macOS the over-read lands in zero-filled BSS and happens to
work. On Windows the read crosses into unmapped memory and crashes
with ACCESS_VIOLATION.
@tbdye tbdye force-pushed the fix-opcode-table-overread branch from 0dfc461 to 47bde6c Compare April 7, 2026 05:14
tbdye added a commit to tbdye/AmiFUSE that referenced this pull request Apr 12, 2026
Add windows-latest to the os matrix for integration-tests and
tools-smoke jobs, with exclude blocks that prevent them from running.
This puts the infrastructure in place so that enabling Windows CI
is a single-block deletion once the upstream machine68k fixes land
(cnvogelg/machine68k#8, reinauer#9).
reinauer pushed a commit to reinauer/AmiFUSE that referenced this pull request Apr 12, 2026
Add windows-latest to the os matrix for integration-tests and
tools-smoke jobs, with exclude blocks that prevent them from running.
This puts the infrastructure in place so that enabling Windows CI
is a single-block deletion once the upstream machine68k fixes land
(cnvogelg/machine68k#8, #9).
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.

1 participant