@@ -33,6 +33,42 @@ test_make(VALUE klass, VALUE num)
3333 return Qnil ;
3434}
3535
36+ /*
37+ * Used to verify that rb_data_free does not read rb_data_type_t after dfree.
38+ * This intentionally frees the type descriptor from dfree so ASAN can catch
39+ * stale post-dfree reads.
40+ */
41+ typedef struct {
42+ rb_data_type_t * type ;
43+ char padding [4096 ];
44+ } dynamic_type_data ;
45+
46+ static void
47+ dynamic_type_free (void * ptr )
48+ {
49+ dynamic_type_data * data = ptr ;
50+ xfree (data -> type );
51+ }
52+
53+ static VALUE
54+ test_dynamic_type (VALUE klass )
55+ {
56+ rb_data_type_t * type ;
57+ dynamic_type_data * data ;
58+ VALUE obj ;
59+
60+ type = ALLOC (rb_data_type_t );
61+ memset (type , 0 , sizeof (rb_data_type_t ));
62+ type -> wrap_struct_name = "dynamic_typed_data" ;
63+ type -> function .dfree = dynamic_type_free ;
64+ type -> flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE ;
65+
66+ obj = TypedData_Make_Struct (klass , dynamic_type_data , type , data );
67+ data -> type = type ;
68+
69+ return obj ;
70+ }
71+
3672void
3773Init_typeddata (void )
3874{
@@ -41,4 +77,5 @@ Init_typeddata(void)
4177 rb_define_alloc_func (klass , test_alloc );
4278 rb_define_singleton_method (klass , "check" , test_check , 1 );
4379 rb_define_singleton_method (klass , "make" , test_make , 1 );
80+ rb_define_singleton_method (klass , "dynamic_type" , test_dynamic_type , 0 );
4481}
0 commit comments