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 {

Reply via email to