Skip to content

Commit

Permalink
[iOS][Android] Fix crash in Exception.CaptureDispatchState (#70970)
Browse files Browse the repository at this point in the history
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 copies `foreignExceptionFrame` into a local variable in `CaptureDispatchState`

Fixes #70081
  • Loading branch information
steveisok authored Jun 22, 2022
1 parent 53cfcf3 commit 9b6ce5c
Showing 1 changed file with 12 additions and 5 deletions.
17 changes: 12 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 @@ -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")]
Expand All @@ -72,11 +74,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 @@ -92,7 +100,6 @@ internal DispatchState CaptureDispatchState()
internal void RestoreDispatchState(in DispatchState state)
{
foreignExceptionsFrames = state.StackFrames;

_stackTraceString = null;
}

Expand Down

0 comments on commit 9b6ce5c

Please sign in to comment.