rust-lang / rust-lang/rust

portable_simd: STATUS_HEAP_CORRUPTION on Windows MSVC with Simd<u32, 16> in tight loops

Open
#154,152 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-SIMD C-bug needs-triage O-windows T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Summary

Code using #![feature(portable_simd)] with Simd<u32, 16> packed field arithmetic crashes with STATUS_HEAP_CORRUPTION (Windows exit code 0xC0000374) on x86_64-pc-windows-msvc. The identical code, compiled with the identical nightly compiler version, runs correctly on x86_64-unknown-linux-gnu (tested via WSL2 on the same machine).

Toolchain

  • Crashes: rustc 1.89.0-nightly (be19eda0d 2025-06-22) targeting x86_64-pc-windows-msvc
  • Works: rustc 1.89.0-nightly (be19eda0d 2025-06-22) targeting x86_64-unknown-linux-gnu
  • Both tested on the same hardware (same machine, WSL2 for Linux)

Reproduction

The crash occurs in the stwo Circle STARK prover's LogupTraceGenerator, which performs packed field arithmetic using Simd<u32, 16> (aliased as PackedM31) and [Simd<u32, 16>; 4] (aliased as PackedQM31).

Steps to reproduce using stwo-cairo (the Cairo STARK prover built on stwo):

# Clone stwo-cairo
git clone https://github.com/starkware-libs/stwo-cairo
cd stwo-cairo/stwo_cairo_prover

# Build (requires nightly for portable_simd)
RUSTFLAGS="-C target-cpu=native" cargo build --release --bin run_and_prove

# Run any test program - crashes on Windows, works on Linux
./target/release/run_and_prove \
  --program test_data/test_prove_verify_ret_opcode/compiled.json \
  --proof_path /tmp/proof.json

The program completes the base trace generation and commitment phases, then crashes entering the interaction trace generation phase, which calls LogupTraceGenerator::new_col()write_frac()PackedQM31 arithmetic.

Crash Details

  • Windows exit code: 0xC0000374 = STATUS_HEAP_CORRUPTION
  • No Rust panicstd::panic::set_hook does not fire, RUST_BACKTRACE=full produces no output
  • Process is terminated by Windows heap manager after detecting metadata corruption

What Was Ruled Out

Hypothesis Test Result
Rayon threading bug RAYON_NUM_THREADS=1 Still crashes
Rayon feature interaction Build without parallel feature Still crashes
Stack overflow RUST_MIN_STACK=67108864 Still crashes
Uninitialized memory (uninit_vec) Replaced with vec![T::zero(); n] Still crashes
Out-of-bounds write Added assert!(idx < len) before get_unchecked_mut Assertion never fires, still crashes
AddressSanitizer on Linux RUSTFLAGS="-Zsanitizer=address" Zero errors reported
-C target-cpu=native Tested with and without Crashes both ways

Crashing Code Pattern

The crash occurs during SIMD-packed field arithmetic in stwo's LogupTraceGenerator (source):

// From stwo constraint-framework, prover/logup.rs
pub fn write_frac(&mut self, vec_row: usize, numerator: PackedSecureField, denom: PackedSecureField) {
    unsafe {
        self.numerator.set_packed(vec_row, numerator);  // Simd<u32, 16> stores
        *self.gen.denom.data.get_unchecked_mut(vec_row) = denom;  // PackedQM31 store
    }
}

Where PackedSecureField = PackedQM31 = [Simd<u32, 16>; 4], and set_packed uses get_unchecked_mut to write 4 × Simd<u32, 16> values into column data.

Linux (WSL2) Results

The same build, same code, same compiler version produces correct verified proofs on Linux:

[TIMING] Interaction trace gen: 0.147s     ← Completes (crashes on Windows)
[TIMING] prove_ex: 12.661s
[TIMING] Total prove_cairo: 13.229s
✅ Proved successfully!

Environment

  • OS (crash): Windows 11 (10.0.26200), x86_64
  • OS (works): Linux 6.6.87.2-microsoft-standard-WSL2 via WSL2
  • CPU: Intel Core Ultra 9 285K (Arrow Lake, AVX2 — no AVX-512)

Hypothesis

The MSVC codegen backend for portable_simd generates incorrect machine code for Simd<u32, 16> store operations, producing wider-than-expected writes or misaligned stores that corrupt adjacent heap metadata. The GNU/Linux codegen produces correct code for the identical source. A standalone minimal reproducer using simple Simd<u32, 16> loops does not trigger the bug, suggesting the issue requires specific code patterns (possibly involving multiple packed stores through get_unchecked_mut pointers into Vec data).

@rustbot label A-simd C-bug O-windows T-compiler

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the crash with the stwo-cairo command and compare the Windows MSVC and Linux builds using rustc 1.89.0-nightly. Inspect stwo's crates/constraint-framework/prover/logup.rs around LogupTraceGenerator::write_frac and the Rust portable_simd MSVC codegen path; done means isolating the faulty store behavior and adding a regression test or confirmed fix.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers, operating-systems
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.