[release/6.0] [iOS][Android] Fix crash in Exception.CaptureDispatchState (#71171)
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Tue, 12 Jul 2022 17:59:31 +0000 (12:59 -0500)
committerGitHub <noreply@github.com>
Tue, 12 Jul 2022 17:59:31 +0000 (12:59 -0500)
* [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 https://github.com/dotnet/runtime/issues/70081

* Lock all of CaptureDispatchState

* Marek's feedback

* Remove unnecessary field

Co-authored-by: Steve Pfister <steve.pfister@microsoft.com>
src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs

index a8fda176114d662baee6faf359f56d54f99037d2..7573a63dac45741ab00cddace4b657b3cb7085d3 100644 (file)
@@ -70,11 +70,17 @@ namespace System
                 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;
                 }
@@ -90,7 +96,6 @@ namespace System
         internal void RestoreDispatchState(in DispatchState state)
         {
             foreignExceptionsFrames = state.StackFrames;
-
             _stackTraceString = null;
         }