From 179a700b340d0291092ab7ca548c4a4069c19c64 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Thu, 16 Jul 2015 13:46:32 -0700 Subject: [PATCH] [sgen] Don't crash on canaries when called from `mono_gc_scan_for_specific_ref()`. This function is only ever called from the debugger, and we don't want it to crash when a canary has been overwritten. --- mono/metadata/sgen-mono.c | 6 +++--- mono/sgen/sgen-debug.c | 14 +++++++------- mono/sgen/sgen-gc.c | 8 ++++---- mono/sgen/sgen-gc.h | 9 ++++++--- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/mono/metadata/sgen-mono.c b/mono/metadata/sgen-mono.c index 4e147406783..bb44f590762 100644 --- a/mono/metadata/sgen-mono.c +++ b/mono/metadata/sgen-mono.c @@ -870,7 +870,7 @@ mono_gc_clear_domain (MonoDomain * domain) sgen_remove_finalizers_if (object_in_domain_predicate, domain, i); sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, - (IterateObjectCallbackFunc)clear_domain_process_minor_object_callback, domain, FALSE); + (IterateObjectCallbackFunc)clear_domain_process_minor_object_callback, domain, FALSE, TRUE); /* We need two passes over major and large objects because freeing such objects might give their memory back to the OS @@ -1845,7 +1845,7 @@ mono_gc_set_string_length (MonoString *str, gint32 new_length) * the space to be reclaimed by SGen. */ if (nursery_canaries_enabled () && sgen_ptr_in_nursery (str)) { - CHECK_CANARY_FOR_OBJECT ((GCObject*)str); + CHECK_CANARY_FOR_OBJECT ((GCObject*)str, TRUE); memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2) + CANARY_SIZE); memcpy (new_end + 1 , CANARY_STRING, CANARY_SIZE); } else { @@ -2144,7 +2144,7 @@ mono_gc_walk_heap (int flags, MonoGCReferences callback, void *data) hwi.data = data; sgen_clear_nursery_fragments (); - sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, walk_references, &hwi, FALSE); + sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, walk_references, &hwi, FALSE, TRUE); major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, walk_references, &hwi); sgen_los_iterate_objects (walk_references, &hwi); diff --git a/mono/sgen/sgen-debug.c b/mono/sgen/sgen-debug.c index 5b4f7fe3ce4..79e23ed453b 100644 --- a/mono/sgen/sgen-debug.c +++ b/mono/sgen/sgen-debug.c @@ -336,7 +336,7 @@ setup_valid_nursery_objects (void) if (!valid_nursery_objects) valid_nursery_objects = sgen_alloc_os_memory (DEFAULT_NURSERY_SIZE, SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE, "debugging data"); valid_nursery_object_count = 0; - sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE); + sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE, FALSE); } static gboolean @@ -469,7 +469,7 @@ sgen_check_whole_heap (gboolean allow_missing_pinned) setup_valid_nursery_objects (); broken_heap = FALSE; - sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned, FALSE); + sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned, FALSE, TRUE); major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned); sgen_los_iterate_objects (verify_object_pointers_callback, (void*) (size_t) allow_missing_pinned); @@ -623,7 +623,7 @@ sgen_check_nursery_objects_pinned (gboolean pinned) { sgen_clear_nursery_fragments (); sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, - (IterateObjectCallbackFunc)check_nursery_objects_pinned_callback, (void*) (size_t) pinned /* (void*)&ctx */, FALSE); + (IterateObjectCallbackFunc)check_nursery_objects_pinned_callback, (void*) (size_t) pinned /* (void*)&ctx */, FALSE, TRUE); } static void @@ -679,7 +679,7 @@ sgen_debug_verify_nursery (gboolean do_dump_nursery_content) is_array_fill); } if (nursery_canaries_enabled () && !is_array_fill) { - CHECK_CANARY_FOR_OBJECT ((GCObject*)cur); + CHECK_CANARY_FOR_OBJECT ((GCObject*)cur, TRUE); CANARIFY_SIZE (size); } cur += size; @@ -844,7 +844,7 @@ mono_gc_scan_for_specific_ref (GCObject *key, gboolean precise) scan_object_for_specific_ref_precise = precise; sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, - (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key, TRUE); + (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key, TRUE, FALSE); major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key); @@ -1041,7 +1041,7 @@ sgen_check_for_xdomain_refs (void) LOSObject *bigobj; sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, - (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL, FALSE); + (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL, FALSE, TRUE); major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL); @@ -1216,7 +1216,7 @@ sgen_find_object_for_ptr (char *ptr) if (ptr >= nursery_section->data && ptr < nursery_section->end_data) { found_obj = NULL; sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, - find_object_for_ptr_callback, ptr, TRUE); + find_object_for_ptr_callback, ptr, TRUE, FALSE); if (found_obj) return found_obj; } diff --git a/mono/sgen/sgen-gc.c b/mono/sgen/sgen-gc.c index a24badfaf7c..4b1a1ac1616 100644 --- a/mono/sgen/sgen-gc.c +++ b/mono/sgen/sgen-gc.c @@ -465,7 +465,7 @@ gray_queue_enable_redirect (SgenGrayQueue *queue) } void -sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc callback, void *data, gboolean allow_flags) +sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc callback, void *data, gboolean allow_flags, gboolean fail_on_canaries) { while (start < end) { size_t size; @@ -484,7 +484,7 @@ sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc } if (!sgen_client_object_is_array_fill ((GCObject*)obj)) { - CHECK_CANARY_FOR_OBJECT ((GCObject*)obj); + CHECK_CANARY_FOR_OBJECT ((GCObject*)obj, fail_on_canaries); size = ALIGN_UP (safe_object_get_size ((GCObject*)obj)); callback ((GCObject*)obj, size, data); CANARIFY_SIZE (size); @@ -664,7 +664,7 @@ pin_objects_from_nursery_pin_queue (gboolean do_scan_objects, ScanCopyContext ct * either. */ if (!sgen_client_object_is_array_fill ((GCObject*)search_start)) { - CHECK_CANARY_FOR_OBJECT (search_start); + CHECK_CANARY_FOR_OBJECT (search_start, TRUE); CANARIFY_SIZE (canarified_obj_size); if (addr >= search_start && (char*)addr < (char*)search_start + obj_size) { @@ -1685,7 +1685,7 @@ static void scan_nursery_objects (ScanCopyContext ctx) { sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, - (IterateObjectCallbackFunc)scan_nursery_objects_callback, (void*)&ctx, FALSE); + (IterateObjectCallbackFunc)scan_nursery_objects_callback, (void*)&ctx, FALSE, TRUE); } typedef enum { diff --git a/mono/sgen/sgen-gc.h b/mono/sgen/sgen-gc.h index bc1b131f508..49fb4c1fac1 100644 --- a/mono/sgen/sgen-gc.h +++ b/mono/sgen/sgen-gc.h @@ -384,7 +384,7 @@ void sgen_deregister_root (char* addr); typedef void (*IterateObjectCallbackFunc) (GCObject*, size_t, void*); -void sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc callback, void *data, gboolean allow_flags); +void sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc callback, void *data, gboolean allow_flags, gboolean fail_on_canaries); /* eventually share with MonoThread? */ /* @@ -1056,13 +1056,16 @@ gboolean nursery_canaries_enabled (void); #define CANARY_VALID(addr) (strncmp ((char*) (addr), CANARY_STRING, CANARY_SIZE) == 0) -#define CHECK_CANARY_FOR_OBJECT(addr) if (nursery_canaries_enabled ()) { \ +#define CHECK_CANARY_FOR_OBJECT(addr,fail) if (nursery_canaries_enabled ()) { \ char* canary_ptr = (char*) (addr) + sgen_safe_object_get_size_unaligned ((GCObject *) (addr)); \ if (!CANARY_VALID(canary_ptr)) { \ char canary_copy[CANARY_SIZE +1]; \ strncpy (canary_copy, canary_ptr, CANARY_SIZE); \ canary_copy[CANARY_SIZE] = 0; \ - g_error ("CORRUPT CANARY:\naddr->%p\ntype->%s\nexcepted->'%s'\nfound->'%s'\n", (char*) addr, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE ((addr))), CANARY_STRING, canary_copy); \ + if ((fail)) \ + g_error ("CORRUPT CANARY:\naddr->%p\ntype->%s\nexcepted->'%s'\nfound->'%s'\n", (char*) addr, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE ((addr))), CANARY_STRING, canary_copy); \ + else \ + g_warning ("CORRUPT CANARY:\naddr->%p\ntype->%s\nexcepted->'%s'\nfound->'%s'\n", (char*) addr, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE ((addr))), CANARY_STRING, canary_copy); \ } } #endif /* HAVE_SGEN_GC */ -- 2.25.1