[glib] GVariant: deal with non-8-aligned malloc()
- From: Ryan Lortie <ryanl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] GVariant: deal with non-8-aligned malloc()
- Date: Tue, 25 May 2010 15:27:04 +0000 (UTC)
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]