portable_simd: STATUS_HEAP_CORRUPTION on Windows MSVC with Simd<u32, 16> in tight loops
Nobody has claimed this yet.
- 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)targetingx86_64-pc-windows-msvc - Works:
rustc 1.89.0-nightly (be19eda0d 2025-06-22)targetingx86_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 panic —
std::panic::set_hookdoes not fire,RUST_BACKTRACE=fullproduces 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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