Skip to content

Commit

Permalink
[release/6.0] [iOS][Android] Fix crash in Exception.CaptureDispatchSt…
Browse files Browse the repository at this point in the history
…ate (#71171)

* [iOS][Android] Fix crash in Exception.CaptureDispatchState

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

* Lock all of CaptureDispatchState

* Marek's feedback

* Remove unnecessary field

Co-authored-by: Steve Pfister <[email protected]>
  • Loading branch information
github-actions[bot] and Steve Pfister authored Jul 12, 2022
1 parent 77fb0b2 commit feb1697
Showing 1 changed file with 10 additions and 5 deletions.
15 changes: 10 additions & 5 deletions src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,17 @@ internal DispatchState CaptureDispatchState()
if (stackFrames.Length > 0)
stackFrames[stackFrames.Length - 1].isLastFrameFromForeignException = true;

if (foreignExceptionsFrames != null)
// Make sure foreignExceptionsFrames 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
MonoStackFrame[]? feFrames = foreignExceptionsFrames;

if (feFrames != 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);
var combinedStackFrames = new MonoStackFrame[stackFrames.Length + feFrames.Length];
Array.Copy(feFrames, 0, combinedStackFrames, 0, feFrames.Length);
Array.Copy(stackFrames, 0, combinedStackFrames, feFrames.Length, stackFrames.Length);

stackFrames = combinedStackFrames;
}
Expand All @@ -90,7 +96,6 @@ internal DispatchState CaptureDispatchState()
internal void RestoreDispatchState(in DispatchState state)
{
foreignExceptionsFrames = state.StackFrames;

_stackTraceString = null;
}

Expand Down

0 comments on commit feb1697

Please sign in to comment.