[前][次][番号順一覧][スレッド一覧]

ruby-changes:55209

From: tenderlove <ko1@a...>
Date: Wed, 3 Apr 2019 04:13:18 +0900 (JST)
Subject: [ruby-changes:55209] tenderlove:r67416 (trunk): Poison / verify the freelist

tenderlove	2019-04-03 04:13:07 +0900 (Wed, 03 Apr 2019)

  New Revision: 67416

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=67416

  Log:
    Poison / verify the freelist
    
    This commit just adds poisoning around the freelist to help debugging.
    Also verify that the freelist only contains T_NONE objects when checking
    the heap integrity

  Modified files:
    trunk/gc.c
Index: gc.c
===================================================================
--- gc.c	(revision 67415)
+++ gc.c	(revision 67416)
@@ -1425,9 +1425,12 @@ static inline void https://github.com/ruby/ruby/blob/trunk/gc.c#L1425
 heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
 {
     RVALUE *p = (RVALUE *)obj;
+    unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
+
     p->as.free.flags = 0;
     p->as.free.next = page->freelist;
     page->freelist = p;
+    __asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
 
     if (RGENGC_CHECK_MODE && !is_pointer_to_heap(objspace, p)) {
 	rb_bug("heap_page_add_freeobj: %p is not rvalue.", (void *)p);
@@ -1440,23 +1443,30 @@ heap_page_add_freeobj(rb_objspace_t *obj https://github.com/ruby/ruby/blob/trunk/gc.c#L1443
 static inline void
 heap_add_freepage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
 {
+    unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
     if (page->freelist) {
 	page->free_next = heap->free_pages;
 	heap->free_pages = page;
     }
+    poison_memory_region(&page->freelist, sizeof(RVALUE*));
 }
 
 #if GC_ENABLE_INCREMENTAL_MARK
 static inline int
 heap_add_poolpage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
 {
+    unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
     if (page->freelist) {
 	page->free_next = heap->pooled_pages;
 	heap->pooled_pages = page;
 	objspace->rincgc.pooled_slots += page->free_slots;
+        poison_memory_region(&page->freelist, sizeof(RVALUE*));
+
 	return TRUE;
     }
     else {
+        poison_memory_region(&page->freelist, sizeof(RVALUE*));
+
 	return FALSE;
     }
 }
@@ -1585,6 +1595,7 @@ heap_page_allocate(rb_objspace_t *objspa https://github.com/ruby/ruby/blob/trunk/gc.c#L1595
     }
     page->free_slots = limit;
 
+    poison_memory_region(&page->freelist, sizeof(RVALUE*));
     return page;
 }
 
@@ -1594,8 +1605,10 @@ heap_page_resurrect(rb_objspace_t *objsp https://github.com/ruby/ruby/blob/trunk/gc.c#L1605
     struct heap_page *page = 0, *next;
 
     list_for_each_safe(&heap_tomb->pages, page, next, page_node) {
+        unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
 	if (page->freelist != NULL) {
 	    heap_unlink_page(objspace, heap_tomb, page);
+            poison_memory_region(&page->freelist, sizeof(RVALUE*));
 	    return page;
 	}
     }
@@ -1754,8 +1767,10 @@ heap_get_freeobj_from_next_freepage(rb_o https://github.com/ruby/ruby/blob/trunk/gc.c#L1767
     heap->using_page = page;
 
     GC_ASSERT(page->free_slots != 0);
+    unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
     p = page->freelist;
     page->freelist = NULL;
+    poison_memory_region(&page->freelist, sizeof(RVALUE*));
     page->free_slots = 0;
     unpoison_object((VALUE)p, true);
     return p;
@@ -3745,11 +3760,15 @@ gc_sweep_start_heap(rb_objspace_t *objsp https://github.com/ruby/ruby/blob/trunk/gc.c#L3760
     objspace->rincgc.pooled_slots = 0;
 #endif
     if (heap->using_page) {
-	RVALUE **p = &heap->using_page->freelist;
+        struct heap_page *page = heap->using_page;
+        unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
+
+        RVALUE **p = &page->freelist;
 	while (*p) {
 	    p = &(*p)->as.free.next;
 	}
 	*p = heap->freelist;
+        poison_memory_region(&page->freelist, sizeof(RVALUE*));
 	heap->using_page = NULL;
     }
     heap->freelist = NULL;
@@ -5445,6 +5464,19 @@ gc_verify_heap_pages_(rb_objspace_t *obj https://github.com/ruby/ruby/blob/trunk/gc.c#L5464
     struct heap_page *page = 0;
 
     list_for_each(head, page, page_node) {
+        unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
+        RVALUE *p = page->freelist;
+        while(p) {
+            RVALUE *prev = p;
+            unpoison_object(p, false);
+            if (BUILTIN_TYPE(p) != T_NONE) {
+                fprintf(stderr, "freelist slot expected to be T_NONE but was: %s\n", obj_info((VALUE)p));
+            }
+            p = p->as.free.next;
+            poison_object(prev);
+        }
+        poison_memory_region(&page->freelist, sizeof(RVALUE*));
+
 	if (page->flags.has_remembered_objects == FALSE) {
 	    remembered_old_objects += gc_verify_heap_page(objspace, page, Qfalse);
 	}

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]