dotnet / dotnet/runtime

JIT: (bug) localloc with a negative native-int constant size becomes a zero-sized allocation

Open
#133,582 1 comment 0 reactions 1 assignee Claimed by @AndyAyersMS View on GitHub
area-CodeGen-coreclr
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

## Repro

C#'s `stackalloc` emits `conv.u`, which zero-extends, so the negative constant has to come from IL.

```csharp
using System;
using System.Reflection.Emit;

unsafe class Program
{
delegate byte* Alloc();

static void Main()
{
var m = new DynamicMethod("NegLocalloc", typeof(byte*), Type.EmptyTypes);
m.InitLocals = true;
ILGenerator il = m.GetILGenerator();
il.DeclareLocal(typeof(IntPtr));
il.Emit(OpCodes.Ldc_I4_M1);
il.Emit(OpCodes.Conv_I); // native int -1 == (nuint)ulong.MaxValue bytes
il.Emit(OpCodes.Localloc);
il.Emit(OpCodes.Ret);

byte* p = m.CreateDelegate()();
Console.WriteLine($"localloc returned {(nint)p:X}");
if (p != null) { p[0] = 1; Console.WriteLine(p[0]); }
}
}
```

Run with `DOTNET_TieredCompilation=0`.

## Expected

A request for `(nuint)(-1)` bytes cannot be satisfied, so `localloc` should overflow the stack
rather than succeed.

## Actual

On a **Release** runtime the allocation "succeeds" and hands back a writable pointer:

```
localloc returned 479677EC10
1
```

The size is rounded up and wraps to 0, so the JIT emits a zero-byte allocation but still returns a
non-null pointer; writing through it corrupts unrelated stack memory instead of failing the request.

A Checked runtime asserts five times on the same method (`DOTNET_ContinueOnAssert=1` to see them all):

```
Assertion failed 'layout->GetSize() != 0' in '(dynamicClass):NegLocalloc():ptr' during 'Lowering nodeinfo'
Assertion failed '(amount > 0) && (amount <= UINT_MAX)' in '(dynamicClass):NegLocalloc():ptr' during 'Generate code'
Assertion failed 'amount > 0' in '(dynamicClass):NegLocalloc():ptr' during 'Generate code'
Assertion failed 'spDelta < 0' in '(dynamicClass):NegLocalloc():ptr' during 'Generate code'
Assertion failed 'spDelta < 0' in '(dynamicClass):NegLocalloc():ptr' during 'Generate code'
```

## Platform

Windows x64, .NET 11 (dotnet/runtime main @ a0b86b1e2a). Reproduces on Release and Checked builds
with `DOTNET_TieredCompilation=0`; no special CPU features.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.