Fix crossgen2 JitHost OOM crash: throw on allocation failure#125422
Open
jtschuster wants to merge 8 commits intodotnet:mainfrom
Open
Fix crossgen2 JitHost OOM crash: throw on allocation failure#125422jtschuster wants to merge 8 commits intodotnet:mainfrom
jtschuster wants to merge 8 commits intodotnet:mainfrom
Conversation
crossgen2's JitHost::allocateMemory returned NULL from malloc on OOM, unlike the CoreCLR VM host which uses 'new' (throws bad_alloc). The JIT's ArenaAllocator::allocateNewPage assumes the allocator either succeeds or throws, and immediately dereferences the result without a NULL check, causing an access violation. Throw std::bad_alloc on NULL returns from malloc/calloc so OOM is handled consistently across all JIT hosts. Also catch std::bad_alloc at the JitCompileMethod boundary in jitwrapper.cpp and return CORJIT_OUTOFMEM so the managed caller gets a proper error code instead of an unhandled native exception. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Member
Author
|
/azp run runtime-coreclr crossgen2-composite |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes crossgen2 JitHost out-of-memory behavior by converting allocation failures into std::bad_alloc, and translating those into a JIT “out of memory” result at the JitCompileMethod boundary.
Changes:
- Throw
std::bad_allocwhenmalloc/callocreturnnullptrin the crossgen2 JIT host. - Catch
std::bad_allocinJitCompileMethodand return an out-of-memory status code. - Add
<new>includes forstd::bad_alloc.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/coreclr/tools/aot/jitinterface/jitwrapper.cpp | Catches OOM exceptions at the compile boundary and returns an OOM result. |
| src/coreclr/tools/aot/jitinterface/jithost.cpp | Makes host allocations throw on failure instead of returning nullptr. |
Contributor
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
crossgen2's JitHost::allocateMemory returned NULL from malloc on OOM, unlike the CoreCLR VM host which uses 'new' (throws bad_alloc). The JIT's ArenaAllocator::allocateNewPage assumes the allocator either succeeds or throws, and immediately dereferences the result without a NULL check, causing an access violation. Throw std::bad_alloc on NULL returns from malloc/calloc so OOM is handled consistently across all JIT hosts. Also catch std::bad_alloc at the JitCompileMethod boundary in jitwrapper.cpp and return CORJIT_OUTOFMEM so the managed caller gets a proper error code instead of an unhandled native exception. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Mar 12, 2026
Replace malloc/free with new/delete in crossgen2's jithost.cpp so that OOM throws std::bad_alloc (caught by jitwrapper.cpp as CORJIT_OUTOFMEM) instead of returning null and crashing. Translate CORJIT_OUTOFMEM to OutOfMemoryException in CorInfoImpl.cs so crossgen2 can skip failed methods gracefully. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…chuster/runtime into fix/crossgen2-oom-null-deref
MichalStrehovsky
approved these changes
Mar 13, 2026
The removal of <stdlib.h> (which transitively provided size_t) caused a build failure on Linux where dllexport.h alone does not pull in size_t. Add <stddef.h> which is the minimal header for size_t without pulling in malloc/free. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…chuster/runtime into fix/crossgen2-oom-null-deref
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
src/coreclr/tools/aot/jitinterface/jitwrapper.cpp:14
- In the
std::bad_alloccatch path,ppExceptionis not set before returning, which can leave the out-parameter in an indeterminate state for the caller. Consider explicitly clearing it (e.g., set*ppException = nullptrwhenppExceptionis non-null) before returningCORJIT_OUTOFMEM.
DLL_EXPORT int JitCompileMethod(
| *ppException = pException; | ||
| } | ||
| catch (const std::bad_alloc&) | ||
| { |
| delete[] value; | ||
| } | ||
|
|
||
| virtual void* allocateSlab(size_t size, size_t* pActualSize) |
This was referenced Mar 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
crossgen2's JitHost::allocateMemory returned NULL from malloc on OOM, unlike the CoreCLR VM host which uses 'new' (which throws bad_alloc). The JIT's ArenaAllocator::allocateNewPage assumes the allocator either succeeds or throws, and immediately dereferences the result without a NULL check, causing an access violation. This is happening in crossgen outerloops on ARM and x86. This change should help make those failures more obvious.
Throw std::bad_alloc on NULL returns from malloc/calloc so OOM is handled consistently across all JIT hosts. Also catch std::bad_alloc at the JitCompileMethod boundary in jitwrapper.cpp and return CORJIT_OUTOFMEM so the managed caller gets a proper error code instead of an unhandled native exception.