diff options
author | Aaron Patterson <tenderlove@ruby-lang.org> | 2021-08-31 16:58:29 -0700 |
---|---|---|
committer | Aaron Patterson <tenderlove@ruby-lang.org> | 2021-09-01 10:58:20 -0700 |
commit | 8db269edb3550a85dfab9b193ea115ca36912ced (patch) | |
tree | b50e4f3043f1aa0a7d3c6f87c00cdfe6832b9dcc /ext/-test-/array/concat/to_ary_conact.c | |
parent | 0aa82b592fc3296ffde1f3fff59018a998c3ade0 (diff) |
Guard array when appending
This prevents early collection of the array. The GC doesn't see the
array on the stack when Ruby is compiled with optimizations enabled
Thanks @jhaberman for the test case
[ruby-core:105099] [Bug #18140]
Diffstat (limited to 'ext/-test-/array/concat/to_ary_conact.c')
-rw-r--r-- | ext/-test-/array/concat/to_ary_conact.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/ext/-test-/array/concat/to_ary_conact.c b/ext/-test-/array/concat/to_ary_conact.c new file mode 100644 index 0000000000..a61659a66e --- /dev/null +++ b/ext/-test-/array/concat/to_ary_conact.c @@ -0,0 +1,64 @@ +#include "ruby.h" + +VALUE cFoo; + +// Foo + +typedef struct { + int dummy; +} Foo; + +static void Foo_free(void* _self) { + xfree(_self); +} + +static rb_data_type_t Foo_type = { + "Foo", + {NULL, Foo_free, NULL }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static VALUE Foo_alloc(VALUE klass) { + Foo* _self = ALLOC(Foo); + return TypedData_Wrap_Struct(klass, &Foo_type, _self); +} + +// Bar + +typedef struct { + int dummy; +} Bar; + +static void Bar_free(void* _self) { + xfree(_self); +} + +static rb_data_type_t Bar_type = { + "Bar", + {NULL, Bar_free, NULL }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static VALUE Bar_alloc(VALUE klass) { + Bar* bar = ALLOC(Bar); + return TypedData_Wrap_Struct(klass, &Bar_type, bar); +} + +VALUE Bar_to_ary(VALUE _self) { + VALUE ary = rb_ary_new2(2); + rb_ary_push(ary, Foo_alloc(cFoo)); + rb_ary_push(ary, Foo_alloc(cFoo)); + rb_ary_push(ary, Foo_alloc(cFoo)); + return ary; +} + +void Init_to_ary_concat() { + VALUE mBug = rb_define_module("Bug"); + cFoo = rb_define_class_under(mBug, "Foo", rb_cObject); + rb_gc_register_address(&cFoo); + rb_define_alloc_func(cFoo, Foo_alloc); + + VALUE bar = rb_define_class_under(mBug, "Bar", rb_cObject); + rb_define_alloc_func(bar, Bar_alloc); + rb_define_method(bar, "to_ary", Bar_to_ary, 0); +} |