From 4a80c0540f0f9b3303919ee7209eedfac856a1af Mon Sep 17 00:00:00 2001 From: shyouhei Date: Tue, 6 Nov 2018 10:06:07 +0000 Subject: adopt sanitizer API These APIs are much like . Use them to fine-grain annotate the usage of our memory. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65573 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- gc.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'gc.c') diff --git a/gc.c b/gc.c index bf193d49f9..b38646988d 100644 --- a/gc.c +++ b/gc.c @@ -1434,6 +1434,7 @@ heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj if (RGENGC_CHECK_MODE && !is_pointer_to_heap(objspace, p)) { rb_bug("heap_page_add_freeobj: %p is not rvalue.", (void *)p); } + poison_object(obj); gc_report(3, objspace, "heap_page_add_freeobj: add %p to freelist\n", (void *)obj); } @@ -1758,6 +1759,7 @@ heap_get_freeobj_from_next_freepage(rb_objspace_t *objspace, rb_heap_t *heap) p = page->freelist; page->freelist = NULL; page->free_slots = 0; + unpoison_object((VALUE)p, true); return p; } @@ -1768,6 +1770,7 @@ heap_get_freeobj_head(rb_objspace_t *objspace, rb_heap_t *heap) if (LIKELY(p != NULL)) { heap->freelist = p->as.free.next; } + unpoison_object((VALUE)p, true); return (VALUE)p; } @@ -1778,6 +1781,7 @@ heap_get_freeobj(rb_objspace_t *objspace, rb_heap_t *heap) while (1) { if (LIKELY(p != NULL)) { + unpoison_object((VALUE)p, true); heap->freelist = p->as.free.next; return (VALUE)p; } @@ -2612,8 +2616,11 @@ static int internal_object_p(VALUE obj) { RVALUE *p = (RVALUE *)obj; + void *ptr = __asan_region_is_poisoned(p, SIZEOF_VALUE); + bool used_p = p->as.basic.flags; + unpoison_object(obj, false); - if (p->as.basic.flags) { + if (used_p) { switch (BUILTIN_TYPE(p)) { case T_NODE: UNEXPECTED_NODE(internal_object_p); @@ -2634,6 +2641,9 @@ internal_object_p(VALUE obj) return 0; } } + if (ptr || ! used_p) { + poison_object(obj); + } return 1; } @@ -2924,8 +2934,11 @@ static void finalize_list(rb_objspace_t *objspace, VALUE zombie) { while (zombie) { - VALUE next_zombie = RZOMBIE(zombie)->next; - struct heap_page *page = GET_HEAP_PAGE(zombie); + VALUE next_zombie; + struct heap_page *page; + unpoison_object(zombie, false); + next_zombie = RZOMBIE(zombie)->next; + page = GET_HEAP_PAGE(zombie); run_final(objspace, zombie); @@ -3044,6 +3057,7 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace) for (i = 0; i < heap_allocated_pages; i++) { p = heap_pages_sorted[i]->start; pend = p + heap_pages_sorted[i]->total_slots; while (p < pend) { + unpoison_object((VALUE)p, false); switch (BUILTIN_TYPE(p)) { case T_DATA: if (!DATA_PTR(p) || !RANY(p)->as.data.dfree) break; @@ -3067,6 +3081,7 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace) } break; } + poison_object((VALUE)p); p++; } } @@ -3610,6 +3625,7 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_ if (bitset) { p = offset + i * BITS_BITLENGTH; do { + unpoison_object((VALUE)p, false); if (bitset & 1) { switch (BUILTIN_TYPE(p)) { default: { /* majority case */ @@ -3628,6 +3644,7 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_ heap_page_add_freeobj(objspace, sweep_page, (VALUE)p); gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info((VALUE)p)); freed_slots++; + poison_object((VALUE)p); } break; } @@ -4419,10 +4436,17 @@ gc_mark_maybe(rb_objspace_t *objspace, VALUE obj) { (void)VALGRIND_MAKE_MEM_DEFINED(&obj, sizeof(obj)); if (is_pointer_to_heap(objspace, (void *)obj)) { - int type = BUILTIN_TYPE(obj); + int type; + void *ptr = __asan_region_is_poisoned((void *)obj, SIZEOF_VALUE); + + unpoison_object(obj, false); + type = BUILTIN_TYPE(obj); if (type != T_ZOMBIE && type != T_NONE) { gc_mark_ptr(objspace, obj); } + if (ptr) { + poison_object(obj); + } } } -- cgit v1.2.3