Skip to content

Commit 774be71

Browse files
Fix improper landing object protection from gc
Ruby Hash uses Object#hash as key, and some objects returns non object-id as hash value. Therefore, when two objects with the same hash values are lent by JS-side, the arena protects only single object. This changes to use object-id as hash key explicitly.
1 parent ada15e3 commit 774be71

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

ext/witapi/witapi-core.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,16 @@ void *rb_wasm_handle_fiber_unwind(void (**new_fiber_entry)(void *, void *),
7676
}
7777

7878
static VALUE rb_abi_guest_arena_hash;
79+
static VALUE rb_abi_guest_refcount_hash;
80+
7981
static VALUE rb_abi_lend_object_internal(VALUE obj) {
80-
VALUE ref_count = rb_hash_lookup(rb_abi_guest_arena_hash, obj);
82+
VALUE object_id = rb_obj_id(obj);
83+
VALUE ref_count = rb_hash_lookup(rb_abi_guest_refcount_hash, object_id);
8184
if (NIL_P(ref_count)) {
82-
rb_hash_aset(rb_abi_guest_arena_hash, obj, INT2FIX(1));
85+
rb_hash_aset(rb_abi_guest_arena_hash, object_id, obj);
86+
rb_hash_aset(rb_abi_guest_refcount_hash, object_id, INT2FIX(1));
8387
} else {
84-
rb_hash_aset(rb_abi_guest_arena_hash, obj, INT2FIX(FIX2INT(ref_count) + 1));
88+
rb_hash_aset(rb_abi_guest_refcount_hash, object_id, INT2FIX(FIX2INT(ref_count) + 1));
8589
}
8690
return Qundef;
8791
}
@@ -93,17 +97,19 @@ static void rb_abi_lend_object(VALUE obj) {
9397
}
9498

9599
static VALUE rb_abi_guest_rb_abi_value_dtor_internal(VALUE obj) {
96-
VALUE ref_count = rb_hash_lookup(rb_abi_guest_arena_hash, obj);
100+
VALUE object_id = rb_obj_id(obj);
101+
VALUE ref_count = rb_hash_lookup(rb_abi_guest_refcount_hash, object_id);
97102
if (NIL_P(ref_count)) {
98103
rb_warning("rb_abi_guest_rb_abi_value_dtor: double free detected");
99104
return Qundef;
100105
}
101106
if (ref_count == INT2FIX(1)) {
102-
rb_hash_delete(rb_abi_guest_arena_hash, obj);
103107
RB_WASM_DEBUG_LOG("rb_abi_guest_rb_abi_value_dtor: ref_count == 1\n");
108+
rb_hash_delete(rb_abi_guest_refcount_hash, object_id);
109+
rb_hash_delete(rb_abi_guest_arena_hash, object_id);
104110
} else {
105-
rb_hash_aset(rb_abi_guest_arena_hash, obj, INT2FIX(FIX2INT(ref_count) - 1));
106111
RB_WASM_DEBUG_LOG("rb_abi_guest_rb_abi_value_dtor: ref_count = %d\n", FIX2INT(ref_count));
112+
rb_hash_aset(rb_abi_guest_refcount_hash, object_id, INT2FIX(FIX2INT(ref_count) - 1));
107113
}
108114
return Qundef;
109115
}
@@ -125,7 +131,10 @@ void rb_abi_guest_ruby_init(void) {
125131
RB_WASM_LIB_RT(ruby_init())
126132

127133
rb_abi_guest_arena_hash = rb_hash_new();
134+
rb_abi_guest_refcount_hash = rb_hash_new();
135+
128136
rb_gc_register_mark_object(rb_abi_guest_arena_hash);
137+
rb_gc_register_mark_object(rb_abi_guest_refcount_hash);
129138
}
130139

131140
void rb_abi_guest_ruby_sysinit(rb_abi_guest_list_string_t *args) {

0 commit comments

Comments
 (0)