Skip to content

Commit

Permalink
[iOS][Android] Fix crash in Exception.CaptureDispatchState (dotnet#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 dotnet#70081
  • Loading branch information
steveisok authored and martinpotter committed Sep 12, 2022
1 parent 35fe0cb commit 10ea09a
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 @@ -48,6 +48,8 @@ public DispatchState(MonoStackFrame[]? stackFrames)

private bool HasBeenThrown => _traceIPs != null;

private readonly object frameLock = new object();

public MethodBase? TargetSite
{
get
Expand All @@ -70,11 +72,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 +98,6 @@ internal DispatchState CaptureDispatchState()
internal void RestoreDispatchState(in DispatchState state)
{
foreignExceptionsFrames = state.StackFrames;

_stackTraceString = null;
}

Expand Down

0 comments on commit 10ea09a

Please sign in to comment.