[clr-ios] Fix SIGSEGV in open virtual delegate dispatch with interpreter#126199
Merged
janvorli merged 13 commits intoApr 14, 2026
Conversation
Contributor
|
Tagging subscribers to this area: @BrzVlad, @janvorli, @kg |
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes an interpreter crash on iOS when invoking compiled open virtual delegate targets, and updates AppleMobile/CoreCLR libraries test selection.
Changes:
- Handle open virtual delegates whose resolved target has no interpreter bytecode (
targetIp == NULL) by skipping the delegate argument slot and directly dispatching viaCALL_INTERP_METHOD. - Remove several AppleMobile/CoreCLR test project exclusions from
src/libraries/tests.proj.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/libraries/tests.proj | Removes previously-added AppleMobile/CoreCLR test exclusions (re-enables several Serialization test projects). |
| src/coreclr/vm/interpexec.cpp | Adds a NULL-targetIp open-virtual delegate path that avoids GetTarget() and dispatches the resolved MethodDesc directly. |
BrzVlad
reviewed
Mar 27, 2026
This was referenced Mar 27, 2026
Open
Member
Author
|
/azp run runtime-ioslike |
|
Azure Pipelines successfully started running 1 pipeline(s). |
This was referenced Mar 30, 2026
Wrap the GetTarget/NonVirtualEntry2MethodDesc block in braces so the CALL_DELEGATE_INVOKE goto can legally jump past the OBJECTREF variable initialization. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix ShiftDelegateCallArgs memmove length to use totalArgsSize - firstAlignedDstOffset instead of totalArgsSize - sizeOfArgsUpto16ByteAlignment to avoid reading past actual argument data when pre-alignment size is not 16-byte aligned. - Extend INTOP_CALLDELEGATE_TAIL to carry sizeOfArgsUpto16ByteAlignment and targetArgsSize (oplength 4 -> 6) so the open virtual compiled target path works correctly for tail calls. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Apr 8, 2026
BrzVlad
approved these changes
Apr 9, 2026
Member
Author
|
/azp run runtime-ioslike |
|
Azure Pipelines successfully started running 1 pipeline(s). |
This was referenced Apr 9, 2026
janvorli
reviewed
Apr 10, 2026
janvorli
reviewed
Apr 10, 2026
…check - Revert INTOP_CALLDELEGATE_TAIL to oplength 4; tail calls use the simpler callArgsOffset += INTERP_STACK_SLOT_SIZE approach matching the interpreted tail path. already makes sizeOfArgsUpto16ByteAlignment == targetArgsSize when no V128 arg exists. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Expand INTOP_CALLDELEGATE_TAIL to oplength 6 with size metadata - Use ShiftDelegateCallArgs in interpreted tail path instead of callArgsOffset + INTERP_STACK_SLOT_SIZE which breaks 16-byte alignment - Use ShiftDelegateCallArgs unconditionally in compiled open virtual path Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
src/coreclr/vm/interpexec.cpp:3224
- In the open-virtual + compiled-target path, the tailcall case adjusts callArgsOffset by one slot and then jumps to CALL_INTERP_METHOD. If CALL_INTERP_METHOD ends up invoking a compiled method (targetIp == NULL), the call stub expects the argument block to follow interpreter stack alignment rules from offset 0 (including 16-byte alignment for V128). Bumping the base pointer by 8 can violate those assumptions. Consider either applying the same alignment-preserving shift for this tailcall case (which likely means carrying the size metadata on INTOP_CALLDELEGATE_TAIL too), or falling back to the normal delegate invoke/shuffle-thunk path for tail calls when the resolved target is compiled.
if ((targetMethod = NonVirtualEntry2MethodDesc(targetAddress)) != NULL)
{
// In this case targetMethod holds a pointer to the MethodDesc that will be called by using targetMethodObj as
// the this pointer. This may be the final method (in the case of instance method delegates), or it may be a
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Merged
1 task
15 tasks
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Description
Fix a crash when the interpreter invokes a compiled open virtual delegate target.
When the interpreter's call delegate handler detects an open virtual delegate whose resolved target is compiled (
targetIp == NULL), the code previously fell through to a generic path that calledGetTarget()on the delegate. For open delegates,GetTarget()returns null, which corrupted the argument slot and caused a SIGSEGV.The fix adds a dedicated path for open virtual delegates with compiled targets. It uses
memmoveto shift the call arguments down by one slot (removing the delegate object) while preserving 16-byte alignment for V128 arguments, then jumps toCALL_INTERP_METHODto invoke the resolvedtargetMethoddirectly. The same shifting is applied for interpreted targets in the non-tail-call path. The alignment-preserving shift logic is extracted into aShiftDelegateCallArgs()helper to avoid duplication.Additionally, this re-enables test suites previously excluded under #124325 (except
System.Runtime.Serialization.Xml.Tests, which hits a native stack overflow unrelated to this fix).