summaryrefslogtreecommitdiff
path: root/gck
diff options
context:
space:
mode:
authorPetr Sumbera <petr.sumbera@oracle.com>2020-01-03 16:16:33 +0100
committerDaiki Ueno <dueno@src.gnome.org>2020-01-03 16:40:03 +0100
commit259080ea8e8c12652065b0041c779a450abfbddc (patch)
tree0af9f2f14eaec77afc378355d0c93f3650092fe6 /gck
parentd4b27d8c8fdfce4e14851df6e15bba60197dad94 (diff)
downloadgcr-259080ea8e8c12652065b0041c779a450abfbddc.tar.gz
gck: Avoid unaligned memory access
When a value in GckAttribute is internally allocated, it embeds a refcount (gint) at the beginning the allocated memory. If refcount has a smaller size than the actual value type (e.g., CK_ULONG), it causes unaligned memory access when reading the value. This patch allocates the maximum alignment size for the refcount part so that the following value should always aligned. See merge request GNOME/gcr!26.
Diffstat (limited to 'gck')
-rw-r--r--gck/gck-attributes.c30
1 files changed, 16 insertions, 14 deletions
diff --git a/gck/gck-attributes.c b/gck/gck-attributes.c
index bb57ffe..f3f04ff 100644
--- a/gck/gck-attributes.c
+++ b/gck/gck-attributes.c
@@ -66,13 +66,15 @@ G_STATIC_ASSERT (sizeof (GckRealBuilder) <= sizeof (GckBuilder));
EGG_SECURE_DECLARE (attributes);
+#define MAX_ALIGN 16
+
static guchar *
value_take (gpointer data,
gsize length,
gboolean secure)
{
- gsize len = length + sizeof (gint);
- gint *value;
+ gsize len = length + MAX_ALIGN;
+ guchar *value;
if (secure)
value = egg_secure_realloc (data, len);
@@ -80,17 +82,17 @@ value_take (gpointer data,
value = g_realloc (data, len);
g_assert (value != NULL);
- memmove (value + 1, value, length);
- g_atomic_int_set (value, 1);
- return (guchar *)(value + 1);
+ memmove (value + MAX_ALIGN, value, length);
+ g_atomic_int_set ((gint *)value, 1);
+ return value + MAX_ALIGN;
}
static guchar *
value_blank (gsize length,
gboolean secure)
{
- gsize len = length + sizeof (gint);
- gint *value;
+ gsize len = length + MAX_ALIGN;
+ guchar *value;
if (secure)
value = egg_secure_alloc (len);
@@ -98,8 +100,8 @@ value_blank (gsize length,
value = g_malloc (len);
g_assert (value != NULL);
- g_atomic_int_set (value, 1);
- return (guchar *)(value + 1);
+ g_atomic_int_set ((gint *)value, 1);
+ return value + MAX_ALIGN;
}
static guchar *
@@ -117,12 +119,12 @@ value_new (gconstpointer data,
static guchar *
value_ref (guchar *data)
{
- gint *value = ((gint *)data) - 1;
+ guchar *value = data - MAX_ALIGN;
gint previous;
g_assert (data != NULL);
- previous = g_atomic_int_add (value, 1);
+ previous = g_atomic_int_add ((gint *)value, 1);
if (G_UNLIKELY (previous <= 0)) {
g_warning ("An owned GckAttribute value has been modified outside of the "
"gck library or an invalid attribute was passed to gck_builder_add_attribute()");
@@ -133,13 +135,13 @@ value_ref (guchar *data)
}
static void
-value_unref (gpointer data)
+value_unref (guchar *data)
{
- gint *value = ((gint *)data) - 1;
+ guchar *value = data - MAX_ALIGN;
g_assert (data != NULL);
- if (g_atomic_int_dec_and_test (value)) {
+ if (g_atomic_int_dec_and_test ((gint *)value)) {
if (egg_secure_check (value))
egg_secure_free (value);
else