Skip to content

Wrong code generation for Unsafe.AsRef<T>, Read<T> when T is a structure #64802

@Temp1ar

Description

@Temp1ar

Description

Looks like JIT doesn't properly evaluate the size of a structure when emitting Unsafe.AsRef for structures less than 4 bytes consisting of a single primitive type field. I have structure, storing ushort in it and sometimes get AccessViolationException when trying to read it from the memory.

I created a gist in sharplab.io to illustrate the case.

Reproduction Steps

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ShortStruct
{
  public short myValue;
}

public class Program {
	public static unsafe T Get<T>(void* a) {
		 return Unsafe.AsRef<T>(a);       
	}

        public unsafe static void Main() {
            int a = 1;
            var x = Get<ShortStruct>(&a);
            Console.WriteLine(x);
        }
}

Expected behavior

I expect 2 bytes will be read and the generated code be equivalent to

Program.Get[[System.Int16, System.Private.CoreLib]](Void*)
    L0000: movsx rax, word ptr [rcx]
    L0004: ret

Actual behavior

It actually tries to read 4 bytes

Program.Get[[ShortStruct, _]](Void*)
    L0000: mov eax, [rcx]
    L0002: ret

Regression?

Yes, if I switch the target to .NET Framework (x64) in that sharplab.io gist - everything is generating correctly

Program.Get[[System.Int16, mscorlib]](Void*)
    L0000: mov rax, rcx
    L0003: movsx rax, word [rax]
    L0007: ret

Program.Get[[ShortStruct, _]](Void*)
    L0000: mov rax, rcx
    L0003: movsx rax, word [rax]
    L0007: ret

Known Workarounds

No response

Configuration

At least .NET 6.0 (x64) is affected

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions