From 9b6ce5c9b782239b26b544ae8d02aa2616dfb6f1 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Wed, 22 Jun 2022 18:28:23 -0400 Subject: [PATCH] [iOS][Android] Fix crash in Exception.CaptureDispatchState (#70970) 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 https://github.com/dotnet/runtime/issues/70081 --- .../src/System/Exception.Mono.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs index 25eb031ddaa2b..eea91b4a0be6e 100644 --- a/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs @@ -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")] @@ -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; } @@ -92,7 +100,6 @@ internal DispatchState CaptureDispatchState() internal void RestoreDispatchState(in DispatchState state) { foreignExceptionsFrames = state.StackFrames; - _stackTraceString = null; }