From d8ae32a9ee7763c861bdc31831271d82aa8a4953 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Fri, 18 Oct 2019 19:11:22 -0400 Subject: [PATCH] [bcl] Add null reference checks to Interlocked.Exchange (#17400) * [bcl] Add null reference checks to Interlocked.Exchange and Interlocked.CompareExchange This is to mimic the old behavior in unmanaged when the intrinsic cannot be used. The issue was detected via the coreclr acceptance test: https://github.com/mono/coreclr/blob/mono/tests/src/baseservices/threading/interlocked/exchange/exchangetneg.il * and netcore --- mcs/class/corlib/System.Threading/Interlocked.cs | 8 ++++++++ .../System.Private.CoreLib/src/System.Threading/Interlocked.cs | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/mcs/class/corlib/System.Threading/Interlocked.cs b/mcs/class/corlib/System.Threading/Interlocked.cs index 376ea390578..d63054d5758 100644 --- a/mcs/class/corlib/System.Threading/Interlocked.cs +++ b/mcs/class/corlib/System.Threading/Interlocked.cs @@ -126,6 +126,10 @@ namespace System.Threading [Intrinsic] public static T CompareExchange (ref T location1, T value, T comparand) where T : class { + unsafe { + if (Unsafe.AsPointer (ref location1) == null) + throw new NullReferenceException (); + } // Besides avoiding coop handles for efficiency, // and correctness, this also appears needed to // avoid an assertion failure in the runtime, related to @@ -157,6 +161,10 @@ namespace System.Threading [Intrinsic] public static T Exchange (ref T location1, T value) where T : class { + unsafe { + if (Unsafe.AsPointer (ref location1) == null) + throw new NullReferenceException (); + } // See CompareExchange(T) for comments. // // This is not entirely convincing due to lack of volatile. diff --git a/netcore/System.Private.CoreLib/src/System.Threading/Interlocked.cs b/netcore/System.Private.CoreLib/src/System.Threading/Interlocked.cs index fe48ed4a8fb..0f99892b29b 100644 --- a/netcore/System.Private.CoreLib/src/System.Threading/Interlocked.cs +++ b/netcore/System.Private.CoreLib/src/System.Threading/Interlocked.cs @@ -80,6 +80,10 @@ namespace System.Threading [Intrinsic] public static T CompareExchange (ref T location1, T value, T comparand) where T : class? { + unsafe { + if (Unsafe.AsPointer (ref location1) == null) + throw new NullReferenceException (); + } // Besides avoiding coop handles for efficiency, // and correctness, this also appears needed to // avoid an assertion failure in the runtime, related to @@ -110,6 +114,10 @@ namespace System.Threading [Intrinsic] public static T Exchange (ref T location1, T value) where T : class? { + unsafe { + if (Unsafe.AsPointer (ref location1) == null) + throw new NullReferenceException (); + } // See CompareExchange(T) for comments. // // This is not entirely convincing due to lack of volatile. -- 2.11.4.GIT