[glib/rc-align] Align the reference counted allocations



commit fb395d30ac708af81c955b2a102184af7894e053
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Wed Nov 14 14:43:23 2018 +0000

    Align the reference counted allocations
    
    We need stronger alignment guarantees for the memory allocations done
    through g_rc_box_alloc_full(): while the passed block size may be
    aligned, we're not aligning the private data size; this means the
    overall allocation may become unaligned, and this could raise issues
    when we use the private data size as an offset to access the reference
    count.
    
    Fixes: #1581

 glib/garcbox.c       |  2 +-
 glib/grcbox.c        | 25 +++++++++++++++++--------
 glib/grcboxprivate.h |  2 ++
 3 files changed, 20 insertions(+), 9 deletions(-)
---
diff --git a/glib/garcbox.c b/glib/garcbox.c
index 9c1bd8fe5..cd727d4ec 100644
--- a/glib/garcbox.c
+++ b/glib/garcbox.c
@@ -31,7 +31,7 @@
 
 #include <string.h>
 
-#define G_ARC_BOX(p)            (GArcBox *) (((char *) (p)) - G_ARC_BOX_SIZE)
+#define G_ARC_BOX(p)            (GArcBox *) (((char *) (p)) - G_ARC_BOX_SIZE - STRUCT_ALIGNMENT)
 
 /**
  * SECTION:arcbox
diff --git a/glib/grcbox.c b/glib/grcbox.c
index f31db78ab..bae335c00 100644
--- a/glib/grcbox.c
+++ b/glib/grcbox.c
@@ -162,23 +162,30 @@
  * Since: 2.58.
  */
 
-#define G_RC_BOX(p)             (GRcBox *) (((char *) (p)) - G_RC_BOX_SIZE)
-
 /* We use the same alignment as GTypeInstance and GNU libc's malloc */
-#define STRUCT_ALIGNMENT        (2 * sizeof (gsize))
 #define ALIGN_STRUCT(offset)    ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)
 
+#define G_RC_BOX(p)             (GRcBox *) (((char *) (p)) - G_RC_BOX_SIZE - STRUCT_ALIGNMENT)
+
 gpointer
 g_rc_box_alloc_full (gsize    block_size,
                      gboolean atomic,
                      gboolean clear)
 {
-  /* sizeof GArcBox == sizeof GRcBox */
-  gsize private_size = G_ARC_BOX_SIZE;
+  /* sizeof GArcBox == sizeof GRcBox; we need to align the size of the
+   * private structure to `2 * sizeof(gsize)`, to ensure that the whole
+   * allocation is aligned
+   */
+  gsize private_size = G_ARC_BOX_SIZE + STRUCT_ALIGNMENT;
   gsize real_size;
   char *allocated;
 
-  g_assert (block_size < (G_MAXSIZE - G_ARC_BOX_SIZE));
+  /* In order to ensure that the alignment of the allocation is
+   * respected everywhere, we also need to align the block size
+   */
+  block_size += STRUCT_ALIGNMENT;
+
+  g_assert (block_size < (G_MAXSIZE - private_size));
   real_size = private_size + block_size;
 
 #ifdef ENABLE_VALGRIND
@@ -215,7 +222,8 @@ g_rc_box_alloc_full (gsize    block_size,
   if (atomic)
     {
       GArcBox *real_box = (GArcBox *) allocated;
-      real_box->mem_size = block_size;
+      /* Store the real size */
+      real_box->mem_size = block_size - STRUCT_ALIGNMENT;
 #ifndef G_DISABLE_ASSERT
       real_box->magic = G_BOX_MAGIC;
 #endif
@@ -224,7 +232,8 @@ g_rc_box_alloc_full (gsize    block_size,
   else
     {
       GRcBox *real_box = (GRcBox *) allocated;
-      real_box->mem_size = block_size;
+      /* Store the real size */
+      real_box->mem_size = block_size - STRUCT_ALIGNMENT;
 #ifndef G_DISABLE_ASSERT
       real_box->magic = G_BOX_MAGIC;
 #endif
diff --git a/glib/grcboxprivate.h b/glib/grcboxprivate.h
index 8b0d8dd4e..6e5c07728 100644
--- a/glib/grcboxprivate.h
+++ b/glib/grcboxprivate.h
@@ -51,6 +51,8 @@ typedef struct {
 /* Keep the two refcounted boxes identical in size */
 G_STATIC_ASSERT (sizeof (GRcBox) == sizeof (GArcBox));
 
+#define STRUCT_ALIGNMENT (2 * sizeof (gsize))
+
 #define G_RC_BOX_SIZE sizeof (GRcBox)
 #define G_ARC_BOX_SIZE sizeof (GArcBox)
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]