I replaced the aliased pointers with memcpy.
This makes the issues go away on sparc64 and probably other architectures
where the accessed memory may not be 64-bit aligned.
It had no visible impact on the amd64 build.
Aside from the 3 library functions that had issues, I also had to change a
number of unit tests.
On amd64, the two most crucial functions compile into the same assembly code:
With pointer aliasing:
Dump of assembler code for function gck_value_to_ulong:
0x0000000000013700 <+0>: test %rdi,%rdi
0x0000000000013703 <+3>: je 0x13720 <gck_value_to_ulong+32>
0x0000000000013705 <+5>: cmp $0x8,%rsi
0x0000000000013709 <+9>: jne 0x13720 <gck_value_to_ulong+32>
0x000000000001370b <+11>: mov $0x1,%eax
0x0000000000013710 <+16>: test %rdx,%rdx
0x0000000000013713 <+19>: je 0x13722 <gck_value_to_ulong+34>
0x0000000000013715 <+21>: mov (%rdi),%rcx
0x0000000000013718 <+24>: mov %rcx,(%rdx)
0x000000000001371b <+27>: retq
0x000000000001371c <+28>: nopl 0x0(%rax)
0x0000000000013720 <+32>: xor %eax,%eax
0x0000000000013722 <+34>: retq
With memcpy:
Dump of assembler code for function gck_value_to_ulong:
0x0000000000013730 <+0>: test %rdi,%rdi
0x0000000000013733 <+3>: je 0x13750 <gck_value_to_ulong+32>
0x0000000000013735 <+5>: cmp $0x8,%rsi
0x0000000000013739 <+9>: jne 0x13750 <gck_value_to_ulong+32>
0x000000000001373b <+11>: mov $0x1,%eax
0x0000000000013740 <+16>: test %rdx,%rdx
0x0000000000013743 <+19>: je 0x13752 <gck_value_to_ulong+34>
0x0000000000013745 <+21>: mov (%rdi),%rcx
0x0000000000013748 <+24>: mov %rcx,(%rdx)
0x000000000001374b <+27>: retq
0x000000000001374c <+28>: nopl 0x0(%rax)
0x0000000000013750 <+32>: xor %eax,%eax
0x0000000000013752 <+34>: retq
With pointer aliasing:
Dump of assembler code for function gck_value_to_boolean:
0x0000000000013730 <+0>: test %rdi,%rdi
0x0000000000013733 <+3>: je 0x13750 <gck_value_to_boolean+32>
0x0000000000013735 <+5>: cmp $0x1,%rsi
0x0000000000013739 <+9>: jne 0x13750 <gck_value_to_boolean+32>
0x000000000001373b <+11>: mov $0x1,%eax
0x0000000000013740 <+16>: test %rdx,%rdx
0x0000000000013743 <+19>: je 0x13752 <gck_value_to_boolean+34>
0x0000000000013745 <+21>: xor %ecx,%ecx
0x0000000000013747 <+23>: cmpb $0x0,(%rdi)
0x000000000001374a <+26>: setne %cl
0x000000000001374d <+29>: mov %ecx,(%rdx)
0x000000000001374f <+31>: retq
0x0000000000013750 <+32>: xor %eax,%eax
0x0000000000013752 <+34>: retq
With memcpy:
Dump of assembler code for function gck_value_to_boolean:
0x0000000000013760 <+0>: test %rdi,%rdi
0x0000000000013763 <+3>: je 0x13780 <gck_value_to_boolean+32>
0x0000000000013765 <+5>: cmp $0x1,%rsi
0x0000000000013769 <+9>: jne 0x13780 <gck_value_to_boolean+32>
0x000000000001376b <+11>: mov $0x1,%eax
0x0000000000013770 <+16>: test %rdx,%rdx
0x0000000000013773 <+19>: je 0x13782 <gck_value_to_boolean+34>
0x0000000000013775 <+21>: xor %ecx,%ecx
0x0000000000013777 <+23>: cmpb $0x0,(%rdi)
0x000000000001377a <+26>: setne %cl
0x000000000001377d <+29>: mov %ecx,(%rdx)
0x000000000001377f <+31>: retq
0x0000000000013780 <+32>: xor %eax,%eax
0x0000000000013782 <+34>: retq
On sparc64, gck_value_to_boolean doesn't change, but gck_value_to_ulong gets a
memcpy call to avoid the misaligned memory access:
Dump of assembler code for function gck_value_to_ulong:
0x0000000000016338 <+0>: save %sp, -176, %sp
0x000000000001633c <+4>: xor %i1, 8, %i1
0x0000000000016340 <+8>: clr %g2
0x0000000000016344 <+12>: clr %g1
0x0000000000016348 <+16>: movre %i0, 1, %g2
0x000000000001634c <+20>: movrne %i1, 1, %g1
0x0000000000016350 <+24>: orcc %g2, %g1, %g0
0x0000000000016354 <+28>: bne,pn %icc, 0x16374 <gck_value_to_ulong+60>
0x0000000000016358 <+32>: clr %i5
0x000000000001635c <+36>: brz,pn %i2, 0x16374 <gck_value_to_ulong+60>
0x0000000000016360 <+40>: mov 1, %i5
0x0000000000016364 <+44>: mov 8, %o2
0x0000000000016368 <+48>: mov %i0, %o1
0x000000000001636c <+52>: call 0x134780 <[email protected]>
0x0000000000016370 <+56>: mov %i2, %o0
0x0000000000016374 <+60>: return %i7 + 8
0x0000000000016378 <+64>: sra %o5, 0, %o0
Index: gcr/gck/gck-misc.c
===================================================================
--- gcr.orig/gck/gck-misc.c
+++ gcr/gck/gck-misc.c
@@ -31,6 +31,8 @@
#include <glib/gi18n-lib.h>
+#include <string.h>
+
EGG_SECURE_DEFINE_GLIB_GLOBALS ();
/**
@@ -430,7 +432,7 @@ _gck_ulong_hash (gconstpointer v)
gboolean
_gck_ulong_equal (gconstpointer v1, gconstpointer v2)
{
- return *((const gulong*)v1) == *((const gulong*)v2);
+ return memcmp(v1, v2, sizeof (gulong)) == 0;
}
/**
@@ -451,7 +453,7 @@ gck_value_to_ulong (const guchar *value,
if (!value || length != sizeof (CK_ULONG))
return FALSE;
if (result)
- *result = *((CK_ULONG*)value);
+ memcpy(result, value, sizeof(CK_ULONG));
return TRUE;
}
@@ -470,10 +472,13 @@ gck_value_to_boolean (const guchar *valu
gsize length,
gboolean *result)
{
+ CK_BBOOL tempval = CK_FALSE;
if (!value || length != sizeof (CK_BBOOL))
return FALSE;
- if (result)
- *result = *((CK_BBOOL*)value) ? TRUE : FALSE;
+ if (result) {
+ memcpy(&tempval, value, sizeof(CK_BBOOL));
+ *result = tempval ? TRUE : FALSE;
+ }
return TRUE;
}
Index: gcr/gck/test-gck-attributes.c
===================================================================
--- gcr.orig/gck/test-gck-attributes.c
+++ gcr/gck/test-gck-attributes.c
@@ -55,11 +55,13 @@ static void
test_init_boolean (void)
{
GckAttribute attr;
+ CK_BBOOL ck_value = CK_FALSE;
gck_attribute_init_boolean (&attr, ATTR_TYPE, TRUE);
g_assert (attr.type == ATTR_TYPE);
g_assert (attr.length == sizeof (CK_BBOOL));
- g_assert (*((CK_BBOOL*)attr.value) == CK_TRUE);
+ memcpy(&ck_value, attr.value, sizeof (CK_BBOOL));
+ g_assert (ck_value == CK_TRUE);
gck_attribute_clear (&attr);
}
@@ -88,11 +90,13 @@ static void
test_init_ulong (void)
{
GckAttribute attr;
+ CK_ULONG ck_value = 0;
gck_attribute_init_ulong (&attr, ATTR_TYPE, 88);
g_assert (attr.type == ATTR_TYPE);
g_assert (attr.length == sizeof (CK_ULONG));
- g_assert (*((CK_ULONG*)attr.value) == 88);
+ memcpy(&ck_value, attr.value, sizeof (CK_ULONG));
+ g_assert (ck_value == 88);
gck_attribute_clear (&attr);
}
@@ -154,11 +158,13 @@ static void
test_new_boolean (void)
{
GckAttribute *attr;
+ CK_BBOOL ck_value = CK_FALSE;
attr = gck_attribute_new_boolean (ATTR_TYPE, TRUE);
g_assert (attr->type == ATTR_TYPE);
g_assert (attr->length == sizeof (CK_BBOOL));
- g_assert (*((CK_BBOOL*)attr->value) == CK_TRUE);
+ memcpy(&ck_value, attr->value, sizeof (CK_BBOOL));
+ g_assert (ck_value == CK_TRUE);
gck_attribute_free (attr);
}
@@ -187,11 +193,13 @@ static void
test_new_ulong (void)
{
GckAttribute *attr;
+ CK_ULONG ck_value = 0;
attr = gck_attribute_new_ulong (ATTR_TYPE, 88);
g_assert (attr->type == ATTR_TYPE);
g_assert (attr->length == sizeof (CK_ULONG));
- g_assert (*((CK_ULONG*)attr->value) == 88);
+ memcpy(&ck_value, attr->value, sizeof (CK_ULONG));
+ g_assert (ck_value == 88);
gck_attribute_free (attr);
}
@@ -536,6 +544,7 @@ test_build_boolean (void)
GckAttributes *attrs;
const GckAttribute *attr;
gboolean value;
+ CK_BBOOL ck_value = CK_FALSE;
g_assert (gck_builder_find_boolean (&builder, 5, &value) == FALSE);
@@ -549,7 +558,8 @@ test_build_boolean (void)
g_assert (attr != NULL);
g_assert (attr->type == ATTR_TYPE);
g_assert (attr->length == sizeof (CK_BBOOL));
- g_assert (*((CK_BBOOL*)attr->value) == CK_FALSE);
+ memcpy(&ck_value, attr->value, sizeof (CK_BBOOL));
+ g_assert (ck_value == CK_FALSE);
if (!gck_builder_find_boolean (&builder, ATTR_TYPE, &value))
g_assert_not_reached ();
g_assert (value == FALSE);
@@ -557,7 +567,8 @@ test_build_boolean (void)
gck_builder_set_boolean (&builder, ATTR_TYPE, TRUE);
g_assert (attr->type == ATTR_TYPE);
g_assert (attr->length == sizeof (CK_BBOOL));
- g_assert (*((CK_BBOOL*)attr->value) == CK_TRUE);
+ memcpy(&ck_value, attr->value, sizeof (CK_BBOOL));
+ g_assert (ck_value == CK_TRUE);
if (!gck_builder_find_boolean (&builder, ATTR_TYPE, &value))
g_assert_not_reached ();
g_assert (value == TRUE);
@@ -572,7 +583,8 @@ test_build_boolean (void)
g_assert (attr->type == ATTR_TYPE);
g_assert (attr->length == sizeof (CK_BBOOL));
- g_assert (*((CK_BBOOL*)attr->value) == CK_TRUE);
+ memcpy(&ck_value, attr->value, sizeof (CK_BBOOL));
+ g_assert (ck_value == CK_TRUE);
if (!gck_attributes_find_boolean (attrs, ATTR_TYPE, &value))
g_assert_not_reached ();
@@ -662,6 +674,7 @@ test_build_ulong (void)
GckAttributes *attrs;
const GckAttribute *attr;
gulong value;
+ CK_ULONG ck_value = 0;
g_assert (gck_builder_find_ulong (&builder, 5, &value) == FALSE);
@@ -675,7 +688,8 @@ test_build_ulong (void)
g_assert (attr != NULL);
g_assert (attr->type == ATTR_TYPE);
g_assert (attr->length == sizeof (CK_ULONG));
- g_assert (*((CK_ULONG*)attr->value) == 99);
+ memcpy(&ck_value, attr->value, sizeof (CK_ULONG));
+ g_assert (ck_value == 99);
if (!gck_builder_find_ulong (&builder, ATTR_TYPE, &value))
g_assert_not_reached ();
g_assert (value == 99);
@@ -683,7 +697,8 @@ test_build_ulong (void)
gck_builder_set_ulong (&builder, ATTR_TYPE, 88);
g_assert (attr->type == ATTR_TYPE);
g_assert (attr->length == sizeof (CK_ULONG));
- g_assert (*((CK_ULONG*)attr->value) == 88);
+ memcpy(&ck_value, attr->value, sizeof (CK_ULONG));
+ g_assert (ck_value == 88);
if (!gck_builder_find_ulong (&builder, ATTR_TYPE, &value))
g_assert_not_reached ();
g_assert (value == 88);
@@ -697,7 +712,8 @@ test_build_ulong (void)
g_assert (attr != NULL);
g_assert (attr->type == ATTR_TYPE);
g_assert (attr->length == sizeof (CK_ULONG));
- g_assert (*((CK_ULONG*)attr->value) == 88);
+ memcpy(&ck_value, attr->value, sizeof (CK_ULONG));
+ g_assert (ck_value == 88);
if (!gck_attributes_find_ulong (attrs, ATTR_TYPE, &value))
g_assert_not_reached ();
Index: gcr/gck/gck-attributes.c
===================================================================
--- gcr.orig/gck/gck-attributes.c
+++ gcr/gck/gck-attributes.c
@@ -2814,13 +2814,13 @@ _gck_format_attributes (GString *output,
if (attr->length == GCK_INVALID) {
g_string_append_printf (output, " (-1) INVALID");
} else if (_gck_attribute_is_ulong_of_type (attr, CKA_CLASS)) {
- _gck_format_class (output, *((CK_OBJECT_CLASS_PTR)attr->value));
+ _gck_format_class (output, (CK_OBJECT_CLASS) gck_attribute_get_ulong(attr));
} else if (_gck_attribute_is_ulong_of_type (attr, CKA_X_ASSERTION_TYPE)) {
- _gck_format_assertion_type (output, *((CK_X_ASSERTION_TYPE *)attr->value));
+ _gck_format_assertion_type (output, (CK_X_ASSERTION_TYPE) gck_attribute_get_ulong(attr));
} else if (_gck_attribute_is_ulong_of_type (attr, CKA_CERTIFICATE_TYPE)) {
- _gck_format_certificate_type (output, *((CK_CERTIFICATE_TYPE *)attr->value));
+ _gck_format_certificate_type (output, (CK_CERTIFICATE_TYPE) gck_attribute_get_ulong(attr));
} else if (_gck_attribute_is_ulong_of_type (attr, CKA_KEY_TYPE)) {
- _gck_format_key_type (output, *((CK_KEY_TYPE *)attr->value));
+ _gck_format_key_type (output, (CK_KEY_TYPE) gck_attribute_get_ulong(attr));
} else if (_gck_attribute_is_sensitive (attr)) {
g_string_append_printf (output, " (%lu) NOT-PRINTED", attr->length);
} else {