Skip to content
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

Fix x86 InlinedCallFrame popping during EH #2215

Merged
merged 4 commits into from
Feb 3, 2020

Conversation

janvorli
Copy link
Member

@janvorli janvorli commented Jan 27, 2020

There is a bug in InlinedCallFrame popping on x86 during EH with R2R
compiled code. The code is popping this frame if it is at the top of
the explicit frames stack before executing catch handler. But it
is missing a check to see if the frame was actually in the unwound part
of the stack. So in some corner cases, it can end up popping a frame
that belongs to an active pinvoke somewhere up the call chain.

The fix is to do the popping only if the InlinedCallFrame is located at
an address smaller than the resume ESP.

Close #2240

@janvorli
Copy link
Member Author

Fixes a problem blocking PR #1929. I've ran corefx tests on Windows x86 with this fix applied on top of the changes from that PR and they have passed.

cc: @clamp03.

{
// The current explicit frame is below the resume esp and it is an inlined call frame with an active call.
//
Copy link
Member

Choose a reason for hiding this comment

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

Nit: You can fix typos in the comment below while you are on it:

unlined
pinovoke

@@ -1868,8 +1868,10 @@ NOINLINE LPVOID COMPlusEndCatchWorker(Thread * pThread)
// Sync managed exception state, for the managed thread, based upon any active exception tracker
pThread->SyncManagedExceptionState(fIsDebuggerHelperThread);

if (InlinedCallFrame::FrameHasActiveCall(pThread->m_pFrame))
if ((pThread->m_pFrame < esp) && InlinedCallFrame::FrameHasActiveCall(pThread->m_pFrame))
Copy link
Member

Choose a reason for hiding this comment

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

How does this work?

I believe that we need to check whether the frame is within the method that we are resuming into, ie we need to check whether pFrame < callerESP.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, you are right that this would not work for the case when the location we resume to is in the same function as the pinvoke frame. It works when it is anywhere up the call chain.

Copy link
Member

Choose a reason for hiding this comment

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

I would not expect the current version of the change to fix the problem.

Anyway, this is not a new problem. #1929 was just unlucky to hit it. I have opened #2240 to track it and added workaround to #1929 to make forward progress.

@jkotas
Copy link
Member

jkotas commented Feb 1, 2020

Could you please also delete the workaround for this bug from AssemblyNative::InternalLoad ?

There is a bug in InlinedCallFrame popping on x86 during EH with R2R
compiled code. The code is popping this frame if it is at the top of
the explicit frames stack before executing catch handler. But it
is missing a check to see if the frame was actually in the unwound part
of the stack. So in some corner cases, it can end up popping a frame
that belongs to an active pinvoke somewhere up the call chain.

The fix is to do the popping only if the InlinedCallFrame is located at
an address smaller than the resume ESP.
The correct ESP to use for detecting the InlinedCallFrame affected by
the current exception handling is the the ESP of the caller of the
method that contains the exception handler.

I have moved the check to a different location where the CrawlFrame with
the context of the exception handler is still available and we can
unwind it to get the caller's SP.
@janvorli janvorli force-pushed the fix-x86-inlinedcallframe-pop branch from 7c32f98 to 54720ec Compare February 1, 2020 20:29
@janvorli
Copy link
Member Author

janvorli commented Feb 3, 2020

@jkotas I've removed the workaround for the issue, can you please take a look again?

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.

Thanks!

@janvorli janvorli merged commit c4f3454 into dotnet:master Feb 3, 2020
@janvorli janvorli deleted the fix-x86-inlinedcallframe-pop branch February 3, 2020 18:16
@ghost ghost locked as resolved and limited conversation to collaborators Dec 11, 2020
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.

[Windows x86] InlinedCallFrame popping during EH corrupts Frame chain
2 participants