From ca00667e829f91f4c15d8208b23fb95da98a251b Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Wed, 22 Dec 2021 20:13:55 +0200 Subject: [PATCH 1/3] [interp] Don't throw NRE if size if 0 during cpblk/initblk --- src/mono/mono/mini/interp/interp.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 56d4134d91a700..0042db4978197d 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -6804,18 +6804,20 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CPBLK) { gpointer dest = LOCAL_VAR (ip [1], gpointer); gpointer src = LOCAL_VAR (ip [2], gpointer); - if (!dest || !src) + gint32 size = LOCAL_VAR (ip [3], gint32); + if (size && (!dest || !src)) THROW_EX (mono_get_exception_null_reference(), ip); - /* FIXME: value and size may be int64... */ - memcpy (dest, src, LOCAL_VAR (ip [3], gint32)); + else + memcpy (dest, src, size); ip += 4; MINT_IN_BREAK; } MINT_IN_CASE(MINT_INITBLK) { gpointer dest = LOCAL_VAR (ip [1], gpointer); - NULL_CHECK (dest); - /* FIXME: value and size may be int64... */ - memset (dest, LOCAL_VAR (ip [2], gint32), LOCAL_VAR (ip [3], gint32)); + gint32 size = LOCAL_VAR (ip [3], gint32); + if (size) + NULL_CHECK (dest); + memset (dest, LOCAL_VAR (ip [2], gint32), size); ip += 4; MINT_IN_BREAK; } From b08c47dd4ddc45366f710c887b7e5eda45fa6693 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Wed, 22 Dec 2021 20:36:52 +0200 Subject: [PATCH 2/3] [interp] Change size to unsigned for initblk/cpblk --- src/mono/mono/mini/interp/interp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 0042db4978197d..040e1169c77f43 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -6804,7 +6804,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_CPBLK) { gpointer dest = LOCAL_VAR (ip [1], gpointer); gpointer src = LOCAL_VAR (ip [2], gpointer); - gint32 size = LOCAL_VAR (ip [3], gint32); + guint32 size = LOCAL_VAR (ip [3], guint32); if (size && (!dest || !src)) THROW_EX (mono_get_exception_null_reference(), ip); else @@ -6814,7 +6814,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; } MINT_IN_CASE(MINT_INITBLK) { gpointer dest = LOCAL_VAR (ip [1], gpointer); - gint32 size = LOCAL_VAR (ip [3], gint32); + guint32 size = LOCAL_VAR (ip [3], guint32); if (size) NULL_CHECK (dest); memset (dest, LOCAL_VAR (ip [2], gint32), size); From ecf0a316a33bdad06dd63cf5c3cc63f3994c7fb7 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Wed, 22 Dec 2021 20:41:39 +0200 Subject: [PATCH 3/3] Remove redundant check --- .../System.Private.CoreLib/src/System/Span.cs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Span.cs b/src/libraries/System.Private.CoreLib/src/System/Span.cs index a5580b2472d078..b512a53a632a7b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Span.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Span.cs @@ -284,18 +284,11 @@ public void Fill(T value) { if (Unsafe.SizeOf() == 1) { -#if MONO - // Mono runtime's implementation of initblk performs a null check on the address. - // We'll perform a length check here to avoid passing a null address in the empty span case. - if (_length != 0) -#endif - { - // Special-case single-byte types like byte / sbyte / bool. - // The runtime eventually calls memset, which can efficiently support large buffers. - // We don't need to check IsReferenceOrContainsReferences because no references - // can ever be stored in types this small. - Unsafe.InitBlockUnaligned(ref Unsafe.As(ref _pointer.Value), Unsafe.As(ref value), (uint)_length); - } + // Special-case single-byte types like byte / sbyte / bool. + // The runtime eventually calls memset, which can efficiently support large buffers. + // We don't need to check IsReferenceOrContainsReferences because no references + // can ever be stored in types this small. + Unsafe.InitBlockUnaligned(ref Unsafe.As(ref _pointer.Value), Unsafe.As(ref value), (uint)_length); } else {