Skip to content

Fix x86 EH for UnmanagedCallersOnly methods #58796

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 9, 2021

Conversation

janvorli
Copy link
Member

@janvorli janvorli commented Sep 8, 2021

There is a bug in the exception handling on x86 when exception is
propagated from a method marked with UnmanagedCallersOnly attribute to
an immediate caller that's also managed (and calls the method via a
native delegate). In this case, there is no native frame in between and
the stack walker accidentally skips the InlinedCallFrame processing
during first pass of exception handling. The InlinedCallFrame is expected
to be processed before the related PInvoke IL stub and it doesn't happen
in this case, as a native frame is required to make the stack frame iterator
move to the explicit InlinedCallFrame. The fact that it is not processed
results in ignoring the upper limit on the stack walk and walking the stack
further than expected.

This change fixes it by detecting the direct transition from
UnmanagedCallersOnly to managed caller and forces the stack frame
iterator to process the InlinedCallFrame.

Fixes #57915

There is a bug in the exception handling on x86 when exception is
propagated from a method marked with UnmanagedCallersOnly attribute to
an immediate caller that's also managed (and calls the method via a
native delegate). In this case, there is no native frame in between and
the stack walker accidentally skips the InlinedCallFrame processing
during first pass of exception handling. The InlinedCallFrame is expected
to be processed before the related PInvoke IL stub and it doesn't happen
in this case, as a native frame is required to make the stack frame iterator
move to the explicit InlinedCallFrame. The fact that it is not processed
results in ignoring the upper limit on the stack walk and walking the stack
further than expected.

This change fixes it by detecting the direct transition from
UnmanagedCallersOnly to managed caller and forces the stack frame
iterator to process the InlinedCallFrame.
@ghost
Copy link

ghost commented Sep 8, 2021

I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label.

@janvorli janvorli requested a review from jkotas September 8, 2021 12:04
@janvorli janvorli self-assigned this Sep 8, 2021
@janvorli janvorli added this to the 7.0.0 milestone Sep 8, 2021
@janvorli
Copy link
Member Author

janvorli commented Sep 8, 2021

cc: @AaronRobinsonMSFT

@janvorli janvorli force-pushed the fix-x86-eh-unmanagedcallers branch from 62f65f1 to 36861ee Compare September 8, 2021 19:37
@@ -3135,6 +3137,12 @@ void StackFrameIterator::PostProcessingForManagedFrames(void)
m_exInfoWalk.WalkToPosition(GetRegdisplaySP(m_crawl.pRD), (m_flags & POPFRAMES));
#endif // ELIMINATE_FEF

#ifdef TARGET_X86
hdrInfo gcHdrInfo;
DecodeGCHdrInfo(m_crawl.codeInfo.GetGCInfoToken(), 0, &gcHdrInfo);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All other places that decode GCInfo in this file go through m_crawl.GetCodeManager(). Is it worth following the pattern?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, but let me do that as a separate cleanup so that this change is just a fix for the bug. I will need to add a new method to the EECodeManager and then I'd use it in the exceptionhandling.cpp too where we currently also have this raw decoding.

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@janvorli janvorli merged commit 7754114 into dotnet:main Sep 9, 2021
@janvorli janvorli deleted the fix-x86-eh-unmanagedcallers branch September 9, 2021 08:54
@ghost ghost locked as resolved and limited conversation to collaborators Oct 9, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[JitStressWithRandomNumbers] UnmanagedCallersOnlyTest fails.
3 participants