[Interpreter] Fix localloc to guarantee 16-byte stack alignment#125720
[Interpreter] Fix localloc to guarantee 16-byte stack alignment#125720
Conversation
|
Tagging subscribers to this area: @BrzVlad, @janvorli, @kg |
…NMENT Co-authored-by: radekdoulik <4147484+radekdoulik@users.noreply.github.com>
|
|
||
| #ifdef FEATURE_INTERPRETER | ||
|
|
||
| #include <minipal.h> |
There was a problem hiding this comment.
Fixed in 648462e. minipal.h has no include guards, so adding it explicitly caused a duplicate definition of VMToOSInterface — it's already available via common.h, which is force-included as a precompiled header for all cee_wks_core VM files (same reason interpexec.cpp can use VMToOSInterface::AlignedAllocate without an explicit include).
Co-authored-by: BrzVlad <4720621+BrzVlad@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes CoreCLR interpreter localloc alignment to guarantee 16-byte alignment (matching INTERP_STACK_ALIGNMENT), addressing failures in ShowLocallocAlignment and preventing misaligned stackalloc buffers on interpreter platforms (e.g., WASM).
Changes:
- Allocate frame data fragments with
VMToOSInterface::AlignedAllocate(INTERP_STACK_ALIGNMENT, ...)and free withAlignedFree. - Align bump allocations in
FrameDataAllocator::Alloc()toINTERP_STACK_ALIGNMENTinstead ofsizeof(void*).
Comments suppressed due to low confidence (1)
src/coreclr/vm/interpframeallocator.cpp:94
- If the first fragment allocation fails (or a fragment’s backing allocation fails),
pFirstcan be left non-null whilepCurrentis still null, and the partially-constructed fragment isn’t deleted. This can corrupt the allocator state: after thenullptrreturn triggersOutOfMemoryException, subsequentAlloccalls will skip thepFirst == nullptrpath and then dereferencepCurrent.
Consider allocating into a temporary FrameDataFragment* and only assigning to pFirst/pCurrent after verifying pFrameStart != nullptr; otherwise delete the fragment before returning failure (same pattern should be applied for later fragment allocations too).
if (pFirst == nullptr)
{
pFirst = new (nothrow) FrameDataFragment(size);
if (pFirst == nullptr || pFirst->pFrameStart == nullptr)
{
return nullptr;
}
FrameDataAllocator::Alloc()was aligning localloc buffers tosizeof(void*)(4–8 bytes) instead ofINTERP_STACK_ALIGNMENT(16 bytes), causing theShowLocallocAlignmentregression test to fail on any platform using the CoreCLR interpreter (e.g., WASM).Description
mallocwithVMToOSInterface::AlignedAllocate(INTERP_STACK_ALIGNMENT, size)so every fragment's base address is 16-byte aligned. Pairfree→VMToOSInterface::AlignedFreeaccordingly.ALIGN_UP(size, sizeof(void*))→ALIGN_UP(size, INTERP_STACK_ALIGNMENT)sopFramePosadvances by a multiple of 16, keeping it aligned across all subsequent allocations and afterPopInforestores.VMToOSInterfaceis already available in allcee_wks_coreVM files viacommon.h, which is force-included as a precompiled header (seesrc/coreclr/vm/wks/CMakeLists.txt). No additional include is needed.Customer Impact
Programs using
stackalloc(localloc) under the CoreCLR interpreter receive misaligned pointers. On WASM and other platforms requiring 16-byte alignment (e.g., for SIMD), this causes incorrect behavior or crashes.Regression
Not a regression in a released build; this is a correctness gap in the interpreter that has existed since its introduction.
Testing
Existing
JIT/Regression/Dev11/External/dev11_239804/ShowLocallocAlignmenttest covers this scenario. Fullclr+libsbuild verified clean on Linux x64.Risk
Low. The change is isolated to
interpframeallocator.cpp— a single file only compiled underFEATURE_INTERPRETER. Both allocation paths (AlignedAllocate/AlignedFree) are already used elsewhere in the interpreter for the main stack (interpexec.cpp). No behavioral change outside the interpreter.Original prompt
📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.