From 397ae49d328563d2810b919ad7c76a7ac6af0fb7 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Thu, 23 Dec 2021 10:46:50 +0200 Subject: [PATCH] [mono][interp] Remove null check during initblk/cpblk with size 0 (#63086) --- src/libraries/System.Private.CoreLib/src/System/Span.cs | 17 +++++------------ src/mono/mono/mini/interp/interp.c | 14 ++++++++------ 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Span.cs b/src/libraries/System.Private.CoreLib/src/System/Span.cs index a5580b2..b512a53 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 @@ namespace System { 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 { diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 56d4134..040e116 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) + guint32 size = LOCAL_VAR (ip [3], guint32); + 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)); + guint32 size = LOCAL_VAR (ip [3], guint32); + if (size) + NULL_CHECK (dest); + memset (dest, LOCAL_VAR (ip [2], gint32), size); ip += 4; MINT_IN_BREAK; } -- 2.7.4