Skip to content

Commit

Permalink
Fix NativeAOT rethrow bug (#88113)
Browse files Browse the repository at this point in the history
* Fix NativeAOT rethrow bug

The rethrowing incorrectly starts searching for exception clause based
on the previously searched clause for the exception being rethrown. It
should always start from the beginning.

* Cleanup and a regression test
  • Loading branch information
janvorli committed Jun 29, 2023
1 parent 15c5f8b commit 8899ed4
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ public static void RhThrowHwEx(uint exceptionCode, ref ExInfo exInfo)
}

exInfo.Init(exceptionToThrow!, instructionFault);
DispatchEx(ref exInfo._frameIter, ref exInfo, MaxTryRegionIdx);
DispatchEx(ref exInfo._frameIter, ref exInfo);
FallbackFailFast(RhFailFastReason.InternalError, null);
}

Expand All @@ -569,7 +569,7 @@ public static void RhThrowEx(object exceptionObj, ref ExInfo exInfo)
}

exInfo.Init(exceptionObj);
DispatchEx(ref exInfo._frameIter, ref exInfo, MaxTryRegionIdx);
DispatchEx(ref exInfo._frameIter, ref exInfo);
FallbackFailFast(RhFailFastReason.InternalError, null);
}

Expand All @@ -586,11 +586,11 @@ public static void RhRethrow(ref ExInfo activeExInfo, ref ExInfo exInfo)
object rethrownException = activeExInfo.ThrownException;

exInfo.Init(rethrownException, ref activeExInfo);
DispatchEx(ref exInfo._frameIter, ref exInfo, activeExInfo._idxCurClause);
DispatchEx(ref exInfo._frameIter, ref exInfo);
FallbackFailFast(RhFailFastReason.InternalError, null);
}

private static void DispatchEx(scoped ref StackFrameIterator frameIter, ref ExInfo exInfo, uint startIdx)
private static void DispatchEx(scoped ref StackFrameIterator frameIter, ref ExInfo exInfo)
{
Debug.Assert(exInfo._passNumber == 1, "expected asm throw routine to set the pass");
object exceptionObj = exInfo.ThrownException;
Expand All @@ -604,7 +604,7 @@ private static void DispatchEx(scoped ref StackFrameIterator frameIter, ref ExIn
byte* pCatchHandler = null;
uint catchingTryRegionIdx = MaxTryRegionIdx;

bool isFirstRethrowFrame = (startIdx != MaxTryRegionIdx);
bool isFirstRethrowFrame = (exInfo._kind & ExKind.RethrowFlag) != 0;
bool isFirstFrame = true;

byte* prevControlPC = null;
Expand All @@ -619,6 +619,7 @@ private static void DispatchEx(scoped ref StackFrameIterator frameIter, ref ExIn

OnFirstChanceExceptionViaClassLib(exceptionObj);

uint startIdx = MaxTryRegionIdx;
for (; isValid; isValid = frameIter.Next(&startIdx, &unwoundReversePInvoke))
{
// For GC stackwalking, we'll happily walk across native code blocks, but for EH dispatch, we
Expand Down
30 changes: 30 additions & 0 deletions src/tests/Regressions/coreclr/GitHub_88128/test88128.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Reflection;

public class test88113
{
public static int Main()
{
try
{
throw new Exception("boo");
}
catch (Exception ex2)
{
Console.WriteLine($"1: {ex2}");
try
{
throw;
}
catch (Exception ex3)
{
Console.WriteLine($"2: {ex3}");
}
}

return 100;
}
}
10 changes: 10 additions & 0 deletions src/tests/Regressions/coreclr/GitHub_88128/test88128.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CLRTestPriority>1</CLRTestPriority>
</PropertyGroup>
<ItemGroup>
<Compile Include="test88128.cs" />
</ItemGroup>
</Project>

0 comments on commit 8899ed4

Please sign in to comment.