aboutsummaryrefslogtreecommitdiffstats
path: root/ext/objspace
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2022-02-09 12:14:51 -0800
committerJohn Hawthorn <john@hawthorn.email>2022-02-09 17:32:43 -0800
commit05b1944c53205ffd8c11f1ec2ae6fd48485b55b1 (patch)
treed636fc8f9c26fea58e74439196833282f7e336e3 /ext/objspace
parenta271acf82284a8ee665686ab6e95df5622f4b1e2 (diff)
downloadruby-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.c34
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;
}
}