diff options
| author | John Hawthorn <john@hawthorn.email> | 2025-10-02 12:15:19 -0700 |
|---|---|---|
| committer | John Hawthorn <john@hawthorn.email> | 2025-10-02 13:24:00 -0700 |
| commit | 1f0da240495f0626085fc32161d3f7bcabb409d5 (patch) | |
| tree | 291894a96807fe74f2e0c5f6ee1214dcb9024b63 | |
| parent | 3cd2407045a67838cf2ab949e5164676b6870958 (diff) | |
ASAN poison parent_object after marking
Previously we were tracking down a bug where this was used after being
valid.
Co-authored-by: Luke Gruber <luke.gru@gmail.com>
| -rw-r--r-- | gc/default/default.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/gc/default/default.c b/gc/default/default.c index 1288a44b8e..9b40fed097 100644 --- a/gc/default/default.c +++ b/gc/default/default.c @@ -4544,6 +4544,28 @@ pin_value(st_data_t key, st_data_t value, st_data_t data) return ST_CONTINUE; } +static inline void +gc_mark_set_parent_raw(rb_objspace_t *objspace, VALUE obj, bool old_p) +{ + asan_unpoison_memory_region(&objspace->rgengc.parent_object, sizeof(objspace->rgengc.parent_object), false); + asan_unpoison_memory_region(&objspace->rgengc.parent_object_old_p, sizeof(objspace->rgengc.parent_object_old_p), false); + objspace->rgengc.parent_object = obj; + objspace->rgengc.parent_object_old_p = old_p; +} + +static inline void +gc_mark_set_parent(rb_objspace_t *objspace, VALUE obj) +{ + gc_mark_set_parent_raw(objspace, obj, RVALUE_OLD_P(objspace, obj)); +} + +static inline void +gc_mark_set_parent_invalid(rb_objspace_t *objspace) +{ + asan_poison_memory_region(&objspace->rgengc.parent_object, sizeof(objspace->rgengc.parent_object)); + asan_poison_memory_region(&objspace->rgengc.parent_object_old_p, sizeof(objspace->rgengc.parent_object_old_p)); +} + static void mark_roots(rb_objspace_t *objspace, const char **categoryp) { @@ -4552,8 +4574,7 @@ mark_roots(rb_objspace_t *objspace, const char **categoryp) } while (0) MARK_CHECKPOINT("objspace"); - objspace->rgengc.parent_object = Qundef; - objspace->rgengc.parent_object_old_p = false; + gc_mark_set_parent_raw(objspace, Qundef, false); if (finalizer_table != NULL) { st_foreach(finalizer_table, pin_value, (st_data_t)objspace); @@ -4563,13 +4584,7 @@ mark_roots(rb_objspace_t *objspace, const char **categoryp) rb_gc_save_machine_context(); rb_gc_mark_roots(objspace, categoryp); -} - -static inline void -gc_mark_set_parent(rb_objspace_t *objspace, VALUE obj) -{ - objspace->rgengc.parent_object = obj; - objspace->rgengc.parent_object_old_p = RVALUE_OLD_P(objspace, obj); + gc_mark_set_parent_invalid(objspace); } static void @@ -4577,6 +4592,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) { gc_mark_set_parent(objspace, obj); rb_gc_mark_children(objspace, obj); + gc_mark_set_parent_invalid(objspace); } /** @@ -5986,9 +6002,11 @@ gc_mark_from(rb_objspace_t *objspace, VALUE obj, VALUE parent) { gc_mark_set_parent(objspace, parent); rgengc_check_relation(objspace, obj); - if (gc_mark_set(objspace, obj) == FALSE) return; - gc_aging(objspace, obj); - gc_grey(objspace, obj); + if (gc_mark_set(objspace, obj) != FALSE) { + gc_aging(objspace, obj); + gc_grey(objspace, obj); + } + gc_mark_set_parent_invalid(objspace); } NOINLINE(static void gc_writebarrier_incremental(VALUE a, VALUE b, rb_objspace_t *objspace)); |
