-
Notifications
You must be signed in to change notification settings - Fork 5.3k
[iOS][Android] Fix crash in Exception.CaptureDispatchState #70970
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There is a crash in `Exception.CaptureDispatchState` when called from one thread at the same time another calls into `Exception.RestoreDispatchState`. The reason for the crash is due to the way we do not update `foreignExceptionFrames` in a thread-safe way. `foreignExceptionFrames` is used in both methods and can crash when the size changes before the array is copied. The fix is to lock when reading from and writing to `foreignExceptionFrames`. Fixes #70081
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,6 +49,8 @@ public DispatchState(MonoStackFrame[]? stackFrames) | |
|
|
||
| private bool HasBeenThrown => _traceIPs != null; | ||
|
|
||
| private readonly object frameLock = new object(); | ||
|
|
||
| public MethodBase? TargetSite | ||
| { | ||
| [RequiresUnreferencedCode("Metadata for the method might be incomplete or removed")] | ||
|
|
@@ -74,9 +76,22 @@ internal DispatchState CaptureDispatchState() | |
|
|
||
| if (foreignExceptionsFrames != null) | ||
| { | ||
| var combinedStackFrames = new MonoStackFrame[stackFrames.Length + foreignExceptionsFrames.Length]; | ||
| Array.Copy(foreignExceptionsFrames, 0, combinedStackFrames, 0, foreignExceptionsFrames.Length); | ||
| Array.Copy(stackFrames, 0, combinedStackFrames, foreignExceptionsFrames.Length, stackFrames.Length); | ||
| MonoStackFrame[] combinedStackFrames; | ||
| int fefLength; | ||
|
|
||
| // Make sure foreignExceptionFrames does not change at this point. | ||
| // Otherwise, the Array.Copy into combinedStackFrames can fail due to size differences | ||
| // | ||
| // See https://github.com/dotnet/runtime/issues/70081 | ||
| lock(frameLock) | ||
| { | ||
| fefLength = foreignExceptionsFrames.Length; | ||
|
|
||
| combinedStackFrames = new MonoStackFrame[stackFrames.Length + fefLength]; | ||
| Array.Copy(foreignExceptionsFrames, 0, combinedStackFrames, 0, fefLength); | ||
| } | ||
|
|
||
| Array.Copy(stackFrames, 0, combinedStackFrames, fefLength, stackFrames.Length); | ||
|
|
||
| stackFrames = combinedStackFrames; | ||
| } | ||
|
|
@@ -91,9 +106,14 @@ internal DispatchState CaptureDispatchState() | |
|
|
||
| internal void RestoreDispatchState(in DispatchState state) | ||
| { | ||
| foreignExceptionsFrames = state.StackFrames; | ||
|
|
||
| _stackTraceString = null; | ||
| // Isolate so we can safely update foreignExceptionFrames and CaptureDispatchState can read the correct values | ||
| // | ||
| // See https://github.com/dotnet/runtime/issues/70081 | ||
| lock(frameLock) | ||
| { | ||
| foreignExceptionsFrames = state.StackFrames; | ||
|
||
| _stackTraceString = null; | ||
| } | ||
| } | ||
|
|
||
| // Returns true if setting the _remoteStackTraceString field is legal, false if not (immutable exception). | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this field is not needed