[glib] GVariant: deal with non-8-aligned malloc()



commit a81c2f2c7ad260bc3033648bb274a3b321df8b49
Author: Ryan Lortie <desrt desrt ca>
Date:   Tue May 25 11:25:34 2010 -0400

    GVariant: deal with non-8-aligned malloc()
    
    Closes bug #619585.

 glib/gvariant-serialiser.c |   18 +++++++++++
 glib/tests/gvariant.c      |   72 ++++++++++++++++++++++++++++----------------
 2 files changed, 64 insertions(+), 26 deletions(-)
---
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
index cf23812..a94a485 100644
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -139,6 +139,24 @@ g_variant_serialised_check (GVariantSerialised serialised)
   else
     g_assert (serialised.size == 0 || serialised.data != NULL);
 
+  /* Depending on the native alignment requirements of the machine, the
+   * compiler will insert either 3 or 7 padding bytes after the char.
+   * This will result in the sizeof() the struct being 12 or 16.
+   * Subtract 9 to get 3 or 7 which is a nice bitmask to apply to get
+   * the alignment bits that we "care about" being zero: in the
+   * 4-aligned case, we care about 2 bits, and in the 8-aligned case, we
+   * care about 3 bits.
+   */
+  alignment &= sizeof (struct {
+                         char a;
+                         union {
+                           guint64 x;
+                           void *y;
+                           gdouble z;
+                         } b;
+                       }
+                      ) - 9;
+
   g_assert_cmpint (alignment & (gsize) serialised.data, ==, 0);
 }
 
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
index 3dc2ac0..1a93607 100644
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -22,6 +22,17 @@
 #define INVALIDS "cefjklpwz&@^$"
 #define N_INVALIDS (G_N_ELEMENTS (INVALIDS) - 1)
 
+/* see comment in gvariant-serialiser.c about this madness.
+ *
+ * we use this to get testing of non-strictly-aligned GVariant instances
+ * on machines that can tolerate it.  it is necessary to support this
+ * because some systems have malloc() that returns non-8-aligned
+ * pointers.  it is necessary to have special support in the tests
+ * because on most machines malloc() is 8-aligned.
+ */
+#define ALIGN_BITS (sizeof (struct { char a; union {                       \
+                      guint64 x; void *y; gdouble z; } b; }) - 9)
+
 static gboolean
 randomly (gdouble prob)
 {
@@ -1138,7 +1149,7 @@ random_instance_write (RandomInstance *instance,
   GRand *rand;
   gint i;
 
-  g_assert_cmpint ((gsize) buffer & instance->alignment, ==, 0);
+  g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
 
   rand = g_rand_new_with_seed (instance->seed);
   for (i = 0; i < instance->size; i++)
@@ -1165,7 +1176,7 @@ random_instance_assert (RandomInstance *instance,
   GRand *rand;
   gint i;
 
-  g_assert_cmpint ((gsize) buffer & instance->alignment, ==, 0);
+  g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
   g_assert_cmpint (size, ==, instance->size);
 
   rand = g_rand_new_with_seed (instance->seed);
@@ -1188,7 +1199,7 @@ random_instance_check (RandomInstance *instance,
   GRand *rand;
   gint i;
 
-  g_assert_cmpint ((gsize) buffer & instance->alignment, ==, 0);
+  g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
 
   if (size != instance->size)
     return FALSE;
@@ -1255,9 +1266,10 @@ flavoured_malloc (gsize size, gsize flavour)
 }
 
 static void
-flavoured_free (gpointer data)
+flavoured_free (gpointer data,
+                gsize flavour)
 {
-  g_free ((gpointer) (((gsize) data) & ~7));
+  g_free (((gchar *) data) - flavour);
 }
 
 static void
@@ -1342,7 +1354,7 @@ test_maybe (void)
     guint alignment;
     guint flavour;
 
-    alignment = instance->alignment + 1;
+    alignment = (instance->alignment & ALIGN_BITS) + 1;
 
     for (flavour = 0; flavour < 8; flavour += alignment)
       {
@@ -1360,7 +1372,7 @@ test_maybe (void)
         g_assert (child.type_info == instance->type_info);
         random_instance_assert (instance, child.data, child.size);
         g_variant_type_info_unref (child.type_info);
-        flavoured_free (serialised.data);
+        flavoured_free (serialised.data, flavour);
       }
   }
 
@@ -1465,7 +1477,7 @@ test_array (void)
     guint i;
 
     g_variant_type_info_query (array_info, &alignment, NULL);
-    alignment++;
+    alignment = (alignment & ALIGN_BITS) + 1;
 
     for (flavour = 0; flavour < 8; flavour += alignment)
       {
@@ -1491,7 +1503,7 @@ test_array (void)
             g_variant_type_info_unref (child.type_info);
           }
 
-        flavoured_free (serialised.data);
+        flavoured_free (serialised.data, flavour);
       }
   }
 
@@ -1626,7 +1638,7 @@ test_tuple (void)
     gsize flavour;
     guint i;
 
-    alignment++;
+    alignment = (alignment & ALIGN_BITS) + 1;
 
     for (flavour = 0; flavour < 8; flavour += alignment)
       {
@@ -1652,7 +1664,7 @@ test_tuple (void)
             g_variant_type_info_unref (child.type_info);
           }
 
-        flavoured_free (serialised.data);
+        flavoured_free (serialised.data, flavour);
       }
   }
 
@@ -1714,26 +1726,34 @@ test_variant (void)
   }
 
   {
-    /* variants are 8-aligned, so no extra flavouring */
-    GVariantSerialised serialised;
-    GVariantSerialised child;
+    gsize alignment;
+    gsize flavour;
+
+    /* variants are always 8-aligned */
+    alignment = ALIGN_BITS + 1;
+
+    for (flavour = 0; flavour < 8; flavour += alignment)
+      {
+        GVariantSerialised serialised;
+        GVariantSerialised child;
 
-    serialised.type_info = type_info;
-    serialised.data = flavoured_malloc (needed_size, 0);
-    serialised.size = needed_size;
+        serialised.type_info = type_info;
+        serialised.data = flavoured_malloc (needed_size, flavour);
+        serialised.size = needed_size;
 
-    g_variant_serialiser_serialise (serialised, random_instance_filler,
-                                    (gpointer *) &instance, 1);
+        g_variant_serialiser_serialise (serialised, random_instance_filler,
+                                        (gpointer *) &instance, 1);
 
-    g_assert (memcmp (serialised.data, data, serialised.size) == 0);
-    g_assert (g_variant_serialised_n_children (serialised) == 1);
+        g_assert (memcmp (serialised.data, data, serialised.size) == 0);
+        g_assert (g_variant_serialised_n_children (serialised) == 1);
 
-    child = g_variant_serialised_get_child (serialised, 0);
-    g_assert (child.type_info == instance->type_info);
-    random_instance_check (instance, child.data, child.size);
+        child = g_variant_serialised_get_child (serialised, 0);
+        g_assert (child.type_info == instance->type_info);
+        random_instance_check (instance, child.data, child.size);
 
-    g_variant_type_info_unref (child.type_info);
-    flavoured_free (serialised.data);
+        g_variant_type_info_unref (child.type_info);
+        flavoured_free (serialised.data, flavour);
+      }
   }
 
   g_variant_type_info_unref (type_info);



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