From 6f33b62f39a273fccb78f71513cb5e0dfb987c70 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 13 Mar 2017 16:02:25 -0400 Subject: [PATCH] [runtime] Mark array types with more than 32 dimensions as invalid. Move the check for arrays of void into Array.CreateInstance (), since typeof (void).MakeArrayType () is valid. Fixes #53131. (#4514) --- mcs/class/corlib/Test/System/ArrayTest.cs | 8 ++++++++ mcs/class/corlib/Test/System/TypeTest.cs | 8 ++++++++ mono/metadata/class.c | 14 ++++++++++++-- mono/metadata/icall.c | 11 +++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/mcs/class/corlib/Test/System/ArrayTest.cs b/mcs/class/corlib/Test/System/ArrayTest.cs index 351d312c92d..f8d33b932fa 100644 --- a/mcs/class/corlib/Test/System/ArrayTest.cs +++ b/mcs/class/corlib/Test/System/ArrayTest.cs @@ -779,6 +779,14 @@ public class ArrayTest Array.CreateInstance (typeof (Int32), (long[])null); } + [Test] + public void CreateInstanceVoid () + { + Assert.Throws (delegate () { + Array.CreateInstance (typeof (void), 1); + }); + } + [Test] public void TestGetEnumerator() { String[] s1 = {"this", "is", "a", "test"}; diff --git a/mcs/class/corlib/Test/System/TypeTest.cs b/mcs/class/corlib/Test/System/TypeTest.cs index 100f1c36274..72300155135 100644 --- a/mcs/class/corlib/Test/System/TypeTest.cs +++ b/mcs/class/corlib/Test/System/TypeTest.cs @@ -3068,6 +3068,14 @@ namespace MonoTests.System object o = Array.CreateInstance (typeof (global::System.TypedReference), 1); } + [Test] + public void MakeArrayTypeLargeRank () + { + Assert.Throws (delegate () { + typeof (int).MakeArrayType (33); + }); + } + [ComVisible (true)] public class ComFoo { } diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 0d0952b0c9f..24e9afa16d5 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -6520,11 +6520,11 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) klass->parent = parent; klass->instance_size = mono_class_instance_size (klass->parent); - if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) { + if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF) { /*Arrays of those two types are invalid.*/ MonoError prepared_error; error_init (&prepared_error); - mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid."); + mono_error_set_invalid_program (&prepared_error, "Arrays of System.TypedReference types are invalid."); mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image)); mono_error_cleanup (&prepared_error); } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) { @@ -6597,6 +6597,16 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) klass->this_arg = klass->byval_arg; klass->this_arg.byref = 1; + if (rank > 32) { + MonoError prepared_error; + error_init (&prepared_error); + name = mono_type_get_full_name (klass); + mono_error_set_type_load_class (&prepared_error, klass, "%s has too many dimensions.", name); + mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image)); + mono_error_cleanup (&prepared_error); + g_free (name); + } + mono_loader_lock (); /* Check cache again */ diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 181273de534..2f3b7f7f27f 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -582,6 +582,11 @@ ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray * if (mono_error_set_pending_exception (&error)) return NULL; + if (klass->element_class->byval_arg.type == MONO_TYPE_VOID) { + mono_set_pending_exception (mono_get_exception_not_supported ("Arrays of System.Void are not supported.")); + return NULL; + } + if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0)) /* vectors are not the same as one dimensional arrays with no-zero bounds */ bounded = TRUE; @@ -6097,6 +6102,7 @@ check_for_invalid_type (MonoClass *klass, MonoError *error) name = mono_type_get_full_name (klass); mono_error_set_type_load_name (error, name, g_strdup (""), ""); } + ICALL_EXPORT MonoReflectionTypeHandle ves_icall_RuntimeType_make_array_type (MonoReflectionTypeHandle ref_type, int rank, MonoError *error) { @@ -6114,6 +6120,11 @@ ves_icall_RuntimeType_make_array_type (MonoReflectionTypeHandle ref_type, int ra else aklass = mono_bounded_array_class_get (klass, rank, TRUE); + if (mono_class_has_failure (aklass)) { + mono_error_set_for_class_failure (error, aklass); + return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE); + } + MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type); return mono_type_get_object_handle (domain, &aklass->byval_arg, error); } -- 2.25.1