summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorKJ Tsanaktsidis <ktsanaktsidis@zendesk.com>2024-01-17 11:45:33 +1100
committerKJ Tsanaktsidis <kj@kjtsanaktsidis.id.au>2024-01-19 09:55:12 +1100
commit61da90c1b8d5c9a62d429ef66f000117eca675b3 (patch)
treee93ec1511a30b1c5ce2d4569e8f293ee67678b48 /gc.c
parent3cfcb45ecfb8dde9920220ae65ea6040e456bbd1 (diff)
Mark asan fake stacks during machine stack marking
ASAN leaves a pointer to the fake frame on the stack; we can use the __asan_addr_is_in_fake_stack API to work out the extent of the fake stack and thus mark any VALUEs contained therein. [Bug #20001]
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/gc.c b/gc.c
index a4de957340..2870b39bcf 100644
--- a/gc.c
+++ b/gc.c
@@ -953,6 +953,11 @@ typedef struct rb_objspace {
rb_darray(VALUE *) weak_references;
rb_postponed_job_handle_t finalize_deferred_pjob;
+
+#ifdef RUBY_ASAN_ENABLED
+ rb_execution_context_t *marking_machine_context_ec;
+#endif
+
} rb_objspace_t;
@@ -6821,6 +6826,26 @@ mark_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
static void each_stack_location(rb_objspace_t *objspace, const rb_execution_context_t *ec,
const VALUE *stack_start, const VALUE *stack_end, void (*cb)(rb_objspace_t *, VALUE));
+static void
+gc_mark_machine_stack_location_maybe(rb_objspace_t *objspace, VALUE obj)
+{
+ gc_mark_maybe(objspace, obj);
+
+#ifdef RUBY_ASAN_ENABLED
+ rb_execution_context_t *ec = objspace->marking_machine_context_ec;
+ void *fake_frame_start;
+ void *fake_frame_end;
+ bool is_fake_frame = asan_get_fake_stack_extents(
+ ec->thread_ptr->asan_fake_stack_handle, obj,
+ ec->machine.stack_start, ec->machine.stack_end,
+ &fake_frame_start, &fake_frame_end
+ );
+ if (is_fake_frame) {
+ each_stack_location(objspace, ec, fake_frame_start, fake_frame_end, gc_mark_maybe);
+ }
+#endif
+}
+
#if defined(__wasm__)
@@ -6882,9 +6907,16 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec
SET_STACK_END;
GET_STACK_BOUNDS(stack_start, stack_end, 1);
- each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), gc_mark_maybe);
+#ifdef RUBY_ASAN_ENABLED
+ objspace->marking_machine_context_ec = ec;
+#endif
- each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe);
+ each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), gc_mark_machine_stack_location_maybe);
+ each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_machine_stack_location_maybe);
+
+#ifdef RUBY_ASAN_ENABLED
+ objspace->marking_machine_context_ec = NULL;
+#endif
}
#endif