diff options
author | John Hawthorn <john@hawthorn.email> | 2022-02-09 12:14:51 -0800 |
---|---|---|
committer | John Hawthorn <john@hawthorn.email> | 2022-02-09 17:32:43 -0800 |
commit | 05b1944c53205ffd8c11f1ec2ae6fd48485b55b1 (patch) | |
tree | d636fc8f9c26fea58e74439196833282f7e336e3 /ext/objspace | |
parent | a271acf82284a8ee665686ab6e95df5622f4b1e2 (diff) | |
download | ruby-05b1944c53205ffd8c11f1ec2ae6fd48485b55b1.tar.gz |
objspace: Hide identhash containing internal objs
Inside ObjectSpace.reachable_objects_from we keep an internal identhash
in order to de-duplicate reachable objects when wrapping them as
InternalObject. Previously this hash was not hidden, making it possible
to leak references to those internal objects to Ruby if using
ObjectSpace.each_object.
This commit solves this by hiding the hash. To simplify collection of
values, we instead now just use the hash as a set of visited objects,
and collect an Array (not hidden) of values to be returned.
Diffstat (limited to 'ext/objspace')
-rw-r--r-- | ext/objspace/objspace.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c index ad5bbe7d0c..d33dfeb80a 100644 --- a/ext/objspace/objspace.c +++ b/ext/objspace/objspace.c @@ -712,7 +712,7 @@ iow_internal_object_id(VALUE self) struct rof_data { VALUE refs; - VALUE internals; + VALUE values; }; static void @@ -723,11 +723,15 @@ reachable_object_from_i(VALUE obj, void *data_ptr) VALUE val = obj; if (rb_objspace_markable_object_p(obj)) { - if (rb_objspace_internal_object_p(obj)) { - val = iow_newobj(obj); - rb_ary_push(data->internals, val); - } - rb_hash_aset(data->refs, key, val); + if (NIL_P(rb_hash_lookup(data->refs, key))) { + rb_hash_aset(data->refs, key, Qtrue); + + if (rb_objspace_internal_object_p(obj)) { + val = iow_newobj(obj); + } + + rb_ary_push(data->values, val); + } } } @@ -785,21 +789,21 @@ static VALUE reachable_objects_from(VALUE self, VALUE obj) { if (rb_objspace_markable_object_p(obj)) { - struct rof_data data; + struct rof_data data; - if (rb_typeddata_is_kind_of(obj, &iow_data_type)) { - obj = (VALUE)DATA_PTR(obj); - } + if (rb_typeddata_is_kind_of(obj, &iow_data_type)) { + obj = (VALUE)DATA_PTR(obj); + } - data.refs = rb_ident_hash_new(); - data.internals = rb_ary_new(); + data.refs = rb_obj_hide(rb_ident_hash_new()); + data.values = rb_ary_new(); - rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data); + rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data); - return rb_funcall(data.refs, rb_intern("values"), 0); + return data.values; } else { - return Qnil; + return Qnil; } } |