Ensure special static slots respect alignment. (#43683)
authormonojenkins <jo.shields+jenkins@xamarin.com>
Tue, 5 Jan 2021 21:19:04 +0000 (16:19 -0500)
committerGitHub <noreply@github.com>
Tue, 5 Jan 2021 21:19:04 +0000 (22:19 +0100)
Without proper alignment, this may lead to reference types
being stored at non-pointer aligned offsets. Among other
issues this may lead to the GC not scanning those pointers
properly.

For example, a type such as
```
struct Point
{
    public int X;
    public int Y;
}
```
will have size 8 and alignment 4 on x64 platforms.

If we reuse the special slot allocated for the `Point` type to store
a reference pointer, it may not be pointer aligned.

Co-authored-by: joncham <joncham@users.noreply.github.com>
src/mono/mono/metadata/threads.c

index 1035058..ad2e348 100644 (file)
@@ -126,6 +126,7 @@ struct _StaticDataFreeList {
        StaticDataFreeList *next;
        guint32 offset;
        guint32 size;
+       gint32 align;
 };
 
 typedef struct {
@@ -4932,12 +4933,12 @@ alloc_context_static_data_helper (gpointer key, gpointer value, gpointer user)
 }
 
 static StaticDataFreeList*
-search_slot_in_freelist (StaticDataInfo *static_data, guint32 size, guint32 align)
+search_slot_in_freelist (StaticDataInfo *static_data, guint32 size, gint32 align)
 {
        StaticDataFreeList* prev = NULL;
        StaticDataFreeList* tmp = static_data->freelist;
        while (tmp) {
-               if (tmp->size == size) {
+               if (tmp->size == size && tmp->align == align) {
                        if (prev)
                                prev->next = tmp->next;
                        else
@@ -5095,7 +5096,7 @@ free_context_static_data_helper (gpointer key, gpointer value, gpointer user)
 }
 
 static void
-do_free_special_slot (guint32 offset, guint32 size)
+do_free_special_slot (guint32 offset, guint32 size, gint32 align)
 {
        guint32 static_type = ACCESS_SPECIAL_STATIC_OFFSET (offset, type);
        MonoBitSet **sets;
@@ -5128,6 +5129,7 @@ do_free_special_slot (guint32 offset, guint32 size)
 
                item->offset = offset;
                item->size = size;
+               item->align = align;
 
                item->next = info->freelist;
                info->freelist = item;
@@ -5142,7 +5144,7 @@ do_free_special (gpointer key, gpointer value, gpointer data)
        gint32 align;
        guint32 size;
        size = mono_type_size (field->type, &align);
-       do_free_special_slot (offset, size);
+       do_free_special_slot (offset, size, align);
 }
 
 void