[sgen] Fix race condition in mono_gc_weak_link_get ().
[mono.git] / mono / metadata / sgen-gc.c
index 692a2e9bbe7174a984bf5dfa3556c7503de7beba..b32e70d19c5310fd61cc8b63e1af8c6d516c03ef 100644 (file)
@@ -1248,7 +1248,7 @@ pin_objects_from_addresses (GCMemSection *section, void **start, void **end, voi
                                                if (G_UNLIKELY (MONO_GC_OBJ_PINNED_ENABLED ())) {
                                                        int gen = sgen_ptr_in_nursery (search_start) ? GENERATION_NURSERY : GENERATION_OLD;
                                                        MonoVTable *vt = (MonoVTable*)LOAD_VTABLE (search_start);
-                                                       MONO_GC_OBJ_PINNED (search_start, sgen_safe_object_get_size (search_start), vt->klass->name_space, vt->klass->name, gen);
+                                                       MONO_GC_OBJ_PINNED ((mword)search_start, sgen_safe_object_get_size (search_start), vt->klass->name_space, vt->klass->name, gen);
                                                }
                                                pin_object (search_start);
                                                GRAY_OBJECT_ENQUEUE (queue, search_start);
@@ -1318,7 +1318,7 @@ sgen_pin_object (void *object, GrayQueue *queue)
        if (G_UNLIKELY (MONO_GC_OBJ_PINNED_ENABLED ())) {
                int gen = sgen_ptr_in_nursery (object) ? GENERATION_NURSERY : GENERATION_OLD;
                MonoVTable *vt = (MonoVTable*)LOAD_VTABLE (object);
-               MONO_GC_OBJ_PINNED (object, sgen_safe_object_get_size (object), vt->klass->name_space, vt->klass->name, gen);
+               MONO_GC_OBJ_PINNED ((mword)object, sgen_safe_object_get_size (object), vt->klass->name_space, vt->klass->name, gen);
        }
 }
 
@@ -2701,7 +2701,7 @@ major_do_collection (const char *reason)
                        binary_protocol_pin (bigobj->data, (gpointer)LOAD_VTABLE (bigobj->data), safe_object_get_size (bigobj->data));
                        if (G_UNLIKELY (MONO_GC_OBJ_PINNED_ENABLED ())) {
                                MonoVTable *vt = (MonoVTable*)LOAD_VTABLE (bigobj->data);
-                               MONO_GC_OBJ_PINNED (bigobj->data, sgen_safe_object_get_size ((MonoObject*)bigobj->data), vt->klass->name_space, vt->klass->name, GENERATION_OLD);
+                               MONO_GC_OBJ_PINNED ((mword)bigobj->data, sgen_safe_object_get_size ((MonoObject*)bigobj->data), vt->klass->name_space, vt->klass->name, GENERATION_OLD);
                        }
                        pin_object (bigobj->data);
                        /* FIXME: only enqueue if object has references */
@@ -4414,9 +4414,15 @@ mono_gc_weak_link_remove (void **link_addr)
 MonoObject*
 mono_gc_weak_link_get (void **link_addr)
 {
-       if (!*link_addr)
+       /*
+        * We must only load *link_addr once because it might change
+        * under our feet, and REVEAL_POINTER (NULL) results in an
+        * invalid reference.
+        */
+       void *ptr = *link_addr;
+       if (!ptr)
                return NULL;
-       return (MonoObject*) REVEAL_POINTER (*link_addr);
+       return (MonoObject*) REVEAL_POINTER (ptr);
 }
 
 gboolean
@@ -4928,6 +4934,12 @@ mono_gc_is_critical_method (MonoMethod *method)
        return (method == write_barrier_method || sgen_is_managed_allocator (method));
 }
 
+static gboolean
+sgen_has_critical_method (void)
+{
+       return write_barrier_method || sgen_has_managed_allocator ();
+}
+
 static gboolean
 is_ip_in_managed_allocator (MonoDomain *domain, gpointer ip)
 {
@@ -4939,6 +4951,8 @@ is_ip_in_managed_allocator (MonoDomain *domain, gpointer ip)
 
        if (!ip || !domain)
                return FALSE;
+       if (!sgen_has_critical_method ())
+               return FALSE;
        ji = mono_jit_info_table_find (domain, ip);
        if (!ji)
                return FALSE;