Skip to content

Commit 68d16d5

Browse files
authored
[NativeAot] Null ref return is wrapped in TargetInvocationException (#69838)
When a null ref return method is invoked. Fixes #69755
1 parent 292e8c9 commit 68d16d5

File tree

5 files changed

+12
-26
lines changed

5 files changed

+12
-26
lines changed

src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/ThrowHelpers.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,5 +127,10 @@ public static void ThrowArgumentOutOfRangeException()
127127
{
128128
throw new ArgumentOutOfRangeException();
129129
}
130+
131+
public static void ThrowInvokeNullRefReturned()
132+
{
133+
throw new NullReferenceException(SR.NullReference_InvokeNullRefReturned);
134+
}
130135
}
131136
}

src/coreclr/nativeaot/System.Private.CoreLib/src/System/InvokeUtils.cs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -427,9 +427,6 @@ internal static unsafe object CallDynamicInvokeMethod(
427427
}
428428
}
429429

430-
if (result == NullByRefValueSentinel)
431-
throw new NullReferenceException(SR.NullReference_InvokeNullRefReturned);
432-
433430
return result;
434431
}
435432
}
@@ -671,18 +668,5 @@ public static object DynamicInvokeParamHelperCore(ref ArgSetupState argSetupStat
671668
}
672669
}
673670
}
674-
675-
private static volatile object _nullByRefValueSentinel;
676-
public static object NullByRefValueSentinel
677-
{
678-
get
679-
{
680-
if (_nullByRefValueSentinel == null)
681-
{
682-
Interlocked.CompareExchange(ref _nullByRefValueSentinel, new object(), null);
683-
}
684-
return _nullByRefValueSentinel;
685-
}
686-
}
687671
}
688672
}

src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallConverterThunk.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,9 +1123,9 @@ private static unsafe void InvokeTarget(void* allocatedStackBuffer, ref CallConv
11231123
if (returnType == CorElementType.ELEMENT_TYPE_BYREF && returnValueToCopy == null)
11241124
{
11251125
// This is a byref return and dereferencing it would result in a NullReferenceException.
1126-
// Set the return value to a sentinel that InvokeUtils will recognize.
1127-
// Can't throw from here or we would wrap this in a TargetInvocationException.
1128-
returnValue = InvokeUtils.NullByRefValueSentinel;
1126+
CompilerHelpers.ThrowHelpers.ThrowInvokeNullRefReturned();
1127+
// Unreachable
1128+
returnValue = null;
11291129
}
11301130
else if (RuntimeAugments.IsUnmanagedPointerType(returnTypeRuntimeTypeHandle))
11311131
{

src/coreclr/tools/Common/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -388,9 +388,7 @@ public override MethodIL EmitIL()
388388
//
389389
// !if (ReturnType is ByRef)
390390
// ByRefNull:
391-
// pop
392-
// call InvokeUtils.get_NullByRefValueSentinel
393-
// ret
391+
// throw NullReferenceException
394392

395393
ILCodeLabel lStaticCall = emitter.NewCodeLabel();
396394
ILCodeLabel lProcessReturn = emitter.NewCodeLabel();
@@ -512,9 +510,8 @@ public override MethodIL EmitIL()
512510
if (lByRefReturnNull != null)
513511
{
514512
returnCodeStream.EmitLabel(lByRefReturnNull);
515-
returnCodeStream.Emit(ILOpcode.pop);
516-
returnCodeStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("get_NullByRefValueSentinel", null)));
517-
returnCodeStream.Emit(ILOpcode.ret);
513+
MethodDesc nullReferencedExceptionHelper = Context.GetHelperEntryPoint("ThrowHelpers", "ThrowInvokeNullRefReturned");
514+
returnCodeStream.EmitCallThrowHelper(emitter, nullReferencedExceptionHelper);
518515
}
519516

520517
return emitter.Link(this);

src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1215,7 +1215,7 @@ public static unsafe void TestNullRefReturnOfPointer()
12151215

12161216
PropertyInfo p = typeof(TestClassIntPointer).GetProperty(nameof(TestClassIntPointer.NullRefReturningProp));
12171217
Assert.NotNull(p);
1218-
Assert.Throws<NullReferenceException>(() => p.GetValue(tc));
1218+
Assert.Throws<TargetInvocationException>(() => p.GetValue(tc));
12191219
}
12201220

12211221
public static unsafe void TestByRefLikeRefReturn()

0 commit comments

Comments
 (0)