Skip to content

[wasm] R2R: 32-byte struct passed by value is corrupted (fields shifted by one word) #131639

Description

@pavelsavara

Description

On browser-wasm (CoreCLR) with PublishReadyToRun, a 32-byte struct (four 8-byte fields) passed by value to a method is corrupted: the callee reads it shifted up by one 8-byte word, so each field takes the value of the next and the following argument bleeds in. 16- and 24-byte structs pass correctly.

Repro

using System;

struct S32 { public long A, B, C, D; }

class Program
{
    static string E32(int x, S32 s, int y) => $"{x}|{s.A},{s.B},{s.C},{s.D}|{y}";

    static void Main()
    {
        Console.WriteLine(E32(1, new S32 { A = 31, B = 32, C = 33, D = 34 }, 2));
    }
}

E32 must be ReadyToRun-compiled. Interpreted execution is correct.

Expected

1|31,32,33,34|2

Actual

1|32,33,34,2|0

s.A reads the input B, s.B reads C, s.C reads D, s.D reads the trailing int y (2), and y reads garbage (0) — i.e. the struct argument is read one 8-byte word too high.

Notes

  • 16-byte ({ long, long }) and 24-byte ({ long, long, long }) structs pass correctly; only the 32-byte (four-word) struct is affected.
  • Reproduces with a direct call; reflection-invoking the same method corrupts it further.

Configuration

  • -os browser -a wasm, CoreCLR, PublishReadyToRun (crossgen2, --obj-format:wasm)
  • Reproduces in Node and in the browser.

Note

This issue was written with the assistance of GitHub Copilot.

Metadata

Metadata

Assignees

Labels

arch-wasmWebAssembly architecturearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions