@@ -49,14 +49,27 @@ static gint32 inflated_classes_size;
4949gint32 mono_inflated_methods_size ;
5050static gint32 class_def_count , class_gtd_count , class_ginst_count , class_gparam_count , class_array_count , class_pointer_count ;
5151
52+ typedef struct {
53+ /* inputs */
54+ const char * nspace ;
55+ const char * name ;
56+ gboolean in_corlib ;
57+ gboolean has_value ;
58+ MonoHasValueCallback has_value_callback ;
59+ /* output */
60+ gboolean has_attr ;
61+ gpointer value ;
62+ } FoundAttrUD ;
63+
5264/* Low level lock which protects data structures in this module */
5365static mono_mutex_t classes_mutex ;
5466
5567static gboolean class_kind_may_contain_generic_instances (MonoTypeKind kind );
5668static void mono_generic_class_setup_parent (MonoClass * klass , MonoClass * gtd );
5769static int generic_array_methods (MonoClass * klass );
5870static void setup_generic_array_ifaces (MonoClass * klass , MonoClass * iface , MonoMethod * * methods , int pos , GHashTable * cache );
59- static gboolean class_has_isbyreflike_attribute (MonoClass * klass );
71+ static FoundAttrUD class_has_isbyreflike_attribute (MonoClass * klass );
72+ static FoundAttrUD class_has_inlinearray_attribute (MonoClass * klass );
6073
6174static
6275GENERATE_TRY_GET_CLASS_WITH_CACHE (icollection , "System.Collections.Generic" , "ICollection`1" );
@@ -291,6 +304,9 @@ mono_class_setup_fields (MonoClass *klass)
291304 instance_size = MONO_ABI_SIZEOF (MonoObject );
292305 }
293306
307+ if (m_class_is_inlinearray (klass ) && m_class_inlinearray_value (klass ) <= 0 )
308+ mono_class_set_type_load_failure (klass , "Inline array length property must be positive." );
309+
294310 /* Get the real size */
295311 explicit_size = mono_metadata_packing_from_typedef (klass -> image , klass -> type_token , & packing_size , & real_size );
296312 if (explicit_size )
@@ -359,6 +375,10 @@ mono_class_setup_fields (MonoClass *klass)
359375 mono_class_set_type_load_failure (klass , "Generic class cannot have explicit layout." );
360376 break ;
361377 }
378+ if (m_class_is_inlinearray (klass )) {
379+ mono_class_set_type_load_failure (klass , "Inline array struct must not have explicit layout." );
380+ break ;
381+ }
362382 }
363383 if (mono_type_has_exceptions (field -> type )) {
364384 char * class_name = mono_type_get_full_name (klass );
@@ -699,9 +719,17 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
699719 mono_get_runtime_callbacks ()-> init_class (klass );
700720
701721 // compute is_byreflike
702- if (m_class_is_valuetype (klass ))
703- if (class_has_isbyreflike_attribute (klass ))
722+ if (m_class_is_valuetype (klass )) {
723+ FoundAttrUD attr ;
724+ attr = class_has_isbyreflike_attribute (klass );
725+ if (attr .has_attr )
704726 klass -> is_byreflike = 1 ;
727+ attr = class_has_inlinearray_attribute (klass );
728+ if (attr .has_attr ) {
729+ klass -> is_inlinearray = 1 ;
730+ klass -> inlinearray_value = GPOINTER_TO_INT32 (attr .value );
731+ }
732+ }
705733
706734 mono_loader_unlock ();
707735
@@ -746,65 +774,87 @@ mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
746774 mono_loader_unlock ();
747775}
748776
749- struct FoundAttrUD {
750- /* inputs */
751- const char * nspace ;
752- const char * name ;
753- gboolean in_corlib ;
754- /* output */
755- gboolean has_attr ;
756- };
757-
758777static gboolean
759- has_wellknown_attribute_func (MonoImage * image , guint32 typeref_scope_token , const char * nspace , const char * name , guint32 method_token , gpointer user_data )
778+ has_wellknown_attribute_func (MonoImage * image , guint32 typeref_scope_token , const char * nspace , const char * name , guint32 method_token , guint32 * cols , gpointer user_data )
760779{
761- struct FoundAttrUD * has_attr = (struct FoundAttrUD * )user_data ;
762- if (!strcmp (name , has_attr -> name ) && !strcmp (nspace , has_attr -> nspace )) {
763- has_attr -> has_attr = TRUE;
764- return TRUE;
780+ FoundAttrUD * attr = (FoundAttrUD * )user_data ;
781+ if (!strcmp (name , attr -> name ) && !strcmp (nspace , attr -> nspace )) {
782+ if (attr -> has_value_callback != NULL ) {
783+ attr -> has_value_callback (image , method_token , cols , user_data );
784+ }
785+ attr -> has_attr = TRUE;
765786 }
766787 /* TODO: use typeref_scope_token to check that attribute comes from
767788 * corlib if in_corlib is TRUE, without triggering an assembly load.
768789 * If we're inside corlib, expect the scope to be
769790 * MONO_RESOLUTION_SCOPE_MODULE I think, if we're outside it'll be an
770791 * MONO_RESOLUTION_SCOPE_ASSEMBLYREF and we'll need to check the
771792 * name.*/
772- return FALSE ;
793+ return attr -> has_attr ;
773794}
774795
775- static gboolean
776- class_has_wellknown_attribute ( MonoClass * klass , const char * nspace , const char * name , gboolean in_corlib )
796+ static void
797+ has_inline_array_attribute_value_func ( MonoImage * image , uint32_t method_token , uint32_t * cols , gpointer user_data )
777798{
778- struct FoundAttrUD has_attr ;
779- has_attr .nspace = nspace ;
780- has_attr .name = name ;
781- has_attr .in_corlib = in_corlib ;
782- has_attr .has_attr = FALSE;
799+ FoundAttrUD * attr = (FoundAttrUD * )user_data ;
800+ MonoError error ;
801+ MonoMethod * ctor = mono_get_method_checked (image , method_token , NULL , NULL , & error );
802+ if (ctor ) {
803+ const char * data = mono_metadata_blob_heap (image , cols [MONO_CUSTOM_ATTR_VALUE ]);
804+ uint32_t data_size = mono_metadata_decode_value (data , & data );
805+ MonoDecodeCustomAttr * decoded_attr = mono_reflection_create_custom_attr_data_args_noalloc (image , ctor , (guchar * )data , data_size , & error );
806+ mono_error_assert_ok (& error );
807+ g_assert (decoded_attr -> named_args_num == 0 && decoded_attr -> typed_args_num == 1 );
808+ attr -> value = * (gpointer * )decoded_attr -> typed_args [0 ]-> value .primitive ;
809+ g_free (decoded_attr );
810+ } else {
811+ g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to: %s" , image -> name , method_token , mono_error_get_message (& error ));
812+ }
813+ }
783814
784- mono_class_metadata_foreach_custom_attr (klass , has_wellknown_attribute_func , & has_attr );
815+ static FoundAttrUD
816+ class_has_wellknown_attribute (MonoClass * klass , const char * nspace , const char * name , gboolean in_corlib , gboolean has_value , MonoHasValueCallback callback )
817+ {
818+ FoundAttrUD attr ;
819+ attr .nspace = nspace ;
820+ attr .name = name ;
821+ attr .in_corlib = in_corlib ;
822+ attr .has_attr = FALSE;
823+ attr .has_value = has_value ;
824+ attr .has_value_callback = callback ;
785825
786- return has_attr .has_attr ;
826+ mono_class_metadata_foreach_custom_attr (klass , has_wellknown_attribute_func , & attr );
827+
828+ return attr ;
787829}
788830
789- static gboolean
790- method_has_wellknown_attribute (MonoMethod * method , const char * nspace , const char * name , gboolean in_corlib )
831+ static FoundAttrUD
832+ method_has_wellknown_attribute (MonoMethod * method , const char * nspace , const char * name , gboolean in_corlib , gboolean has_value , MonoHasValueCallback callback )
791833{
792- struct FoundAttrUD has_attr ;
793- has_attr .nspace = nspace ;
794- has_attr .name = name ;
795- has_attr .in_corlib = in_corlib ;
796- has_attr .has_attr = FALSE;
834+ FoundAttrUD attr ;
835+ attr .nspace = nspace ;
836+ attr .name = name ;
837+ attr .in_corlib = in_corlib ;
838+ attr .has_attr = FALSE;
839+ attr .has_value = has_value ;
840+ attr .has_value_callback = callback ;
797841
798- mono_method_metadata_foreach_custom_attr (method , has_wellknown_attribute_func , & has_attr );
842+ mono_method_metadata_foreach_custom_attr (method , has_wellknown_attribute_func , & attr );
799843
800- return has_attr . has_attr ;
844+ return attr ;
801845}
802846
803847
804- static gboolean
848+ static FoundAttrUD
805849class_has_isbyreflike_attribute (MonoClass * klass )
806850{
807- return class_has_wellknown_attribute (klass , "System.Runtime.CompilerServices" , "IsByRefLikeAttribute" , TRUE);
851+ return class_has_wellknown_attribute (klass , "System.Runtime.CompilerServices" , "IsByRefLikeAttribute" , TRUE, FALSE, NULL );
852+ }
853+
854+ static FoundAttrUD
855+ class_has_inlinearray_attribute (MonoClass * klass )
856+ {
857+ return class_has_wellknown_attribute (klass , "System.Runtime.CompilerServices" , "InlineArrayAttribute" , TRUE, TRUE, has_inline_array_attribute_value_func );
808858}
809859
810860
@@ -815,7 +865,8 @@ mono_class_setup_method_has_preserve_base_overrides_attribute (MonoMethod *metho
815865 /* FIXME: implement well known attribute check for dynamic images */
816866 if (image_is_dynamic (image ))
817867 return FALSE;
818- return method_has_wellknown_attribute (method , "System.Runtime.CompilerServices" , "PreserveBaseOverridesAttribute" , TRUE);
868+ FoundAttrUD attr = method_has_wellknown_attribute (method , "System.Runtime.CompilerServices" , "PreserveBaseOverridesAttribute" , TRUE, FALSE, NULL );
869+ return attr .has_attr ;
819870}
820871
821872static gboolean
@@ -868,6 +919,8 @@ mono_class_create_generic_inst (MonoGenericClass *gclass)
868919 klass -> this_arg .type = m_class_get_byval_arg (klass )-> type ;
869920 klass -> this_arg .data .generic_class = klass -> _byval_arg .data .generic_class = gclass ;
870921 klass -> this_arg .byref__ = TRUE;
922+ klass -> is_inlinearray = gklass -> is_inlinearray ;
923+ klass -> inlinearray_value = gklass -> inlinearray_value ;
871924 klass -> enumtype = gklass -> enumtype ;
872925 klass -> valuetype = gklass -> valuetype ;
873926
@@ -2184,6 +2237,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_
21842237 real_size = MONO_ABI_SIZEOF (MonoObject );
21852238 }
21862239
2240+ guint32 inlined_fields = 0 ;
21872241 for (pass = 0 ; pass < passes ; ++ pass ) {
21882242 for (i = 0 ; i < top ; i ++ ){
21892243 gint32 align ;
@@ -2217,6 +2271,17 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_
22172271 }
22182272
22192273 size = mono_type_size (field -> type , & align );
2274+ if (m_class_is_inlinearray (klass )) {
2275+ // Limit the max size of array instance to 1MiB
2276+ const guint32 struct_max_size = 1024 * 1024 ;
2277+ // If size overflows, it returns 0
2278+ size *= m_class_inlinearray_value (klass );
2279+ inlined_fields ++ ;
2280+ if (size == 0 || size > struct_max_size ) {
2281+ mono_class_set_type_load_failure (klass , "Inline array struct size out of bounds, abnormally large." );
2282+ break ;
2283+ }
2284+ }
22202285
22212286 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
22222287 align = packing_size ? MIN (packing_size , align ): align ;
@@ -2244,6 +2309,8 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_
22442309 instance_size &= ~(min_align - 1 );
22452310 }
22462311 }
2312+ if (m_class_is_inlinearray (klass ) && inlined_fields != 1 )
2313+ mono_class_set_type_load_failure (klass , "Inline array struct must have a single field." );
22472314 break ;
22482315 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT : {
22492316 real_size = 0 ;
0 commit comments