@@ -49,14 +49,27 @@ static gint32 inflated_classes_size;
49
49
gint32 mono_inflated_methods_size ;
50
50
static gint32 class_def_count , class_gtd_count , class_ginst_count , class_gparam_count , class_array_count , class_pointer_count ;
51
51
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
+
52
64
/* Low level lock which protects data structures in this module */
53
65
static mono_mutex_t classes_mutex ;
54
66
55
67
static gboolean class_kind_may_contain_generic_instances (MonoTypeKind kind );
56
68
static void mono_generic_class_setup_parent (MonoClass * klass , MonoClass * gtd );
57
69
static int generic_array_methods (MonoClass * klass );
58
70
static 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 );
60
73
61
74
static
62
75
GENERATE_TRY_GET_CLASS_WITH_CACHE (icollection , "System.Collections.Generic" , "ICollection`1" );
@@ -291,6 +304,9 @@ mono_class_setup_fields (MonoClass *klass)
291
304
instance_size = MONO_ABI_SIZEOF (MonoObject );
292
305
}
293
306
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
+
294
310
/* Get the real size */
295
311
explicit_size = mono_metadata_packing_from_typedef (klass -> image , klass -> type_token , & packing_size , & real_size );
296
312
if (explicit_size )
@@ -359,6 +375,10 @@ mono_class_setup_fields (MonoClass *klass)
359
375
mono_class_set_type_load_failure (klass , "Generic class cannot have explicit layout." );
360
376
break ;
361
377
}
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
+ }
362
382
}
363
383
if (mono_type_has_exceptions (field -> type )) {
364
384
char * class_name = mono_type_get_full_name (klass );
@@ -699,9 +719,17 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
699
719
mono_get_runtime_callbacks ()-> init_class (klass );
700
720
701
721
// 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 )
704
726
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
+ }
705
733
706
734
mono_loader_unlock ();
707
735
@@ -746,65 +774,87 @@ mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
746
774
mono_loader_unlock ();
747
775
}
748
776
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
-
758
777
static 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 )
760
779
{
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;
765
786
}
766
787
/* TODO: use typeref_scope_token to check that attribute comes from
767
788
* corlib if in_corlib is TRUE, without triggering an assembly load.
768
789
* If we're inside corlib, expect the scope to be
769
790
* MONO_RESOLUTION_SCOPE_MODULE I think, if we're outside it'll be an
770
791
* MONO_RESOLUTION_SCOPE_ASSEMBLYREF and we'll need to check the
771
792
* name.*/
772
- return FALSE ;
793
+ return attr -> has_attr ;
773
794
}
774
795
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 )
777
798
{
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
+ }
783
814
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 ;
785
825
786
- return has_attr .has_attr ;
826
+ mono_class_metadata_foreach_custom_attr (klass , has_wellknown_attribute_func , & attr );
827
+
828
+ return attr ;
787
829
}
788
830
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 )
791
833
{
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 ;
797
841
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 );
799
843
800
- return has_attr . has_attr ;
844
+ return attr ;
801
845
}
802
846
803
847
804
- static gboolean
848
+ static FoundAttrUD
805
849
class_has_isbyreflike_attribute (MonoClass * klass )
806
850
{
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 );
808
858
}
809
859
810
860
@@ -815,7 +865,8 @@ mono_class_setup_method_has_preserve_base_overrides_attribute (MonoMethod *metho
815
865
/* FIXME: implement well known attribute check for dynamic images */
816
866
if (image_is_dynamic (image ))
817
867
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 ;
819
870
}
820
871
821
872
static gboolean
@@ -868,6 +919,8 @@ mono_class_create_generic_inst (MonoGenericClass *gclass)
868
919
klass -> this_arg .type = m_class_get_byval_arg (klass )-> type ;
869
920
klass -> this_arg .data .generic_class = klass -> _byval_arg .data .generic_class = gclass ;
870
921
klass -> this_arg .byref__ = TRUE;
922
+ klass -> is_inlinearray = gklass -> is_inlinearray ;
923
+ klass -> inlinearray_value = gklass -> inlinearray_value ;
871
924
klass -> enumtype = gklass -> enumtype ;
872
925
klass -> valuetype = gklass -> valuetype ;
873
926
@@ -2184,6 +2237,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_
2184
2237
real_size = MONO_ABI_SIZEOF (MonoObject );
2185
2238
}
2186
2239
2240
+ guint32 inlined_fields = 0 ;
2187
2241
for (pass = 0 ; pass < passes ; ++ pass ) {
2188
2242
for (i = 0 ; i < top ; i ++ ){
2189
2243
gint32 align ;
@@ -2217,6 +2271,17 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_
2217
2271
}
2218
2272
2219
2273
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
+ }
2220
2285
2221
2286
/* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
2222
2287
align = packing_size ? MIN (packing_size , align ): align ;
@@ -2244,6 +2309,8 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_
2244
2309
instance_size &= ~(min_align - 1 );
2245
2310
}
2246
2311
}
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." );
2247
2314
break ;
2248
2315
case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT : {
2249
2316
real_size = 0 ;
0 commit comments