From 4adb1172658f74e6a513bece426005d7f2ba7a04 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Fri, 17 Jun 2022 21:31:25 -0700 Subject: Harden for null byrefs (#70317) * Remove enum_flag_Unrestored usage in boxing stubs. * Add AND instruction (21h) to x86 decoder. * Update mono for null ref in interpreter paths. * Disable test on llvmfullaot and wasm * Handle null destination for intrinsics. --- .../invalid_operations/InvalidOperations.csproj | 12 ++++ .../invalid_operations/ManagedPointers.cs | 84 ++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/tests/baseservices/invalid_operations/InvalidOperations.csproj create mode 100644 src/tests/baseservices/invalid_operations/ManagedPointers.cs (limited to 'src/tests/baseservices') diff --git a/src/tests/baseservices/invalid_operations/InvalidOperations.csproj b/src/tests/baseservices/invalid_operations/InvalidOperations.csproj new file mode 100644 index 00000000000..3c04f092ae8 --- /dev/null +++ b/src/tests/baseservices/invalid_operations/InvalidOperations.csproj @@ -0,0 +1,12 @@ + + + Exe + true + + + + + + + + \ No newline at end of file diff --git a/src/tests/baseservices/invalid_operations/ManagedPointers.cs b/src/tests/baseservices/invalid_operations/ManagedPointers.cs new file mode 100644 index 00000000000..c5357cf0354 --- /dev/null +++ b/src/tests/baseservices/invalid_operations/ManagedPointers.cs @@ -0,0 +1,84 @@ +// 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.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; + +using Xunit; + +public unsafe class ManagedPointers +{ + [Fact] + public static void Validate_BoxingHelpers_NullByRef() + { + Console.WriteLine($"Running {nameof(Validate_BoxingHelpers_NullByRef)}..."); + Assert.Throws(() => + { + object boxed = Unsafe.NullRef(); + }); + Assert.Throws(() => + { + object boxed = Unsafe.NullRef(); + }); + Assert.Throws(() => + { + object boxed = Unsafe.NullRef(); + }); + } + + [Fact] + public static void Validate_GeneratedILStubs_NullByRef() + { + Console.WriteLine($"Running {nameof(Validate_GeneratedILStubs_NullByRef)}..."); + { + var fptr = (delegate*unmanaged)(delegate*unmanaged)&PassByRef; + Assert.Equal(0, fptr(ref Unsafe.NullRef())); + } + + { + var fptr = (delegate*unmanaged)(delegate*unmanaged)&PassByRef; + Assert.Equal(0, fptr(ref Unsafe.NullRef())); + } + + Assert.Throws(() => + { + var fptr = (delegate*unmanaged)(delegate*unmanaged)&PassByRef; + fptr(ref Unsafe.NullRef()); + }); + + [UnmanagedCallersOnly] + static nint PassByRef(void* a) => (nint)a; + } + + [Fact] + public static void Validate_IntrinsicMethodsWithByRef_NullByRef() + { + Console.WriteLine($"Running {nameof(Validate_IntrinsicMethodsWithByRef_NullByRef)}..."); + + Assert.Throws(() => Interlocked.Increment(ref Unsafe.NullRef())); + Assert.Throws(() => Interlocked.Increment(ref Unsafe.NullRef())); + Assert.Throws(() => Interlocked.Decrement(ref Unsafe.NullRef())); + Assert.Throws(() => Interlocked.Decrement(ref Unsafe.NullRef())); + + Assert.Throws(() => Interlocked.And(ref Unsafe.NullRef(), 0)); + Assert.Throws(() => Interlocked.And(ref Unsafe.NullRef(), 0)); + Assert.Throws(() => Interlocked.Or(ref Unsafe.NullRef(), 0)); + Assert.Throws(() => Interlocked.Or(ref Unsafe.NullRef(), 0)); + + Assert.Throws(() => Interlocked.Exchange(ref Unsafe.NullRef(), 0)); + Assert.Throws(() => Interlocked.Exchange(ref Unsafe.NullRef(), 0)); + Assert.Throws(() => Interlocked.Exchange(ref Unsafe.NullRef(), 0)); + Assert.Throws(() => Interlocked.Exchange(ref Unsafe.NullRef(), 0)); + Assert.Throws(() => Interlocked.Exchange(ref Unsafe.NullRef(), new object())); + Assert.Throws(() => Interlocked.Exchange(ref Unsafe.NullRef(), new object())); + + Assert.Throws(() => Interlocked.CompareExchange(ref Unsafe.NullRef(), 0, 0)); + Assert.Throws(() => Interlocked.CompareExchange(ref Unsafe.NullRef(), 0, 0)); + Assert.Throws(() => Interlocked.CompareExchange(ref Unsafe.NullRef(), 0, 0)); + Assert.Throws(() => Interlocked.CompareExchange(ref Unsafe.NullRef(), 0, 0)); + Assert.Throws(() => Interlocked.CompareExchange(ref Unsafe.NullRef(), new object(), new object())); + Assert.Throws(() => Interlocked.CompareExchange(ref Unsafe.NullRef(), new object(), new object())); + } +} \ No newline at end of file -- cgit v1.2.3