Avoid unions in X509_NAME logic.

Cast between T* and ASN1_VALUE* directly, rather than messing with
unions. This is necessary to avoid UB in C++ and is a strict aliasing
violation in C too. (While C does allow type-punning in unions, pointers
to union fields have weird rules. I suspect most of our unions should be
reworked.)

Change-Id: Ibe274a7df5d5826f8c5f335255d196e9b7587105
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42726
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/x509/x_name.c b/crypto/x509/x_name.c
index 7824100..bef9ec4 100644
--- a/crypto/x509/x_name.c
+++ b/crypto/x509/x_name.c
@@ -197,18 +197,8 @@
                             char opt, ASN1_TLC *ctx)
 {
     const unsigned char *p = *in, *q;
-    union {
-        STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
-        ASN1_VALUE *a;
-    } intname = {
-        NULL
-    };
-    union {
-        X509_NAME *x;
-        ASN1_VALUE *a;
-    } nm = {
-        NULL
-    };
+    STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL;
+    X509_NAME *nm = NULL;
     size_t i, j;
     int ret;
     STACK_OF(X509_NAME_ENTRY) *entries;
@@ -220,46 +210,48 @@
     q = p;
 
     /* Get internal representation of Name */
-    ret = ASN1_item_ex_d2i(&intname.a,
+    ASN1_VALUE *intname_val = NULL;
+    ret = ASN1_item_ex_d2i(&intname_val,
                            &p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL),
                            tag, aclass, opt, ctx);
-
     if (ret <= 0)
         return ret;
+    intname = (STACK_OF(STACK_OF_X509_NAME_ENTRY) *)intname_val;
 
     if (*val)
         x509_name_ex_free(val, NULL);
-    if (!x509_name_ex_new(&nm.a, NULL))
+    ASN1_VALUE *nm_val = NULL;
+    if (!x509_name_ex_new(&nm_val, NULL))
         goto err;
+    nm = (X509_NAME *)nm_val;
     /* We've decoded it: now cache encoding */
-    if (!BUF_MEM_grow(nm.x->bytes, p - q))
+    if (!BUF_MEM_grow(nm->bytes, p - q))
         goto err;
-    OPENSSL_memcpy(nm.x->bytes->data, q, p - q);
+    OPENSSL_memcpy(nm->bytes->data, q, p - q);
 
     /* Convert internal representation to X509_NAME structure */
-    for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) {
-        entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname.s, i);
+    for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname); i++) {
+        entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname, i);
         for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) {
             entry = sk_X509_NAME_ENTRY_value(entries, j);
             entry->set = i;
-            if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry))
+            if (!sk_X509_NAME_ENTRY_push(nm->entries, entry))
                 goto err;
             (void)sk_X509_NAME_ENTRY_set(entries, j, NULL);
         }
     }
-    ret = x509_name_canon(nm.x);
+    ret = x509_name_canon(nm);
     if (!ret)
         goto err;
-    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
                                          local_sk_X509_NAME_ENTRY_free);
-    nm.x->modified = 0;
-    *val = nm.a;
+    nm->modified = 0;
+    *val = (ASN1_VALUE *)nm;
     *in = p;
     return ret;
  err:
-    if (nm.x != NULL)
-        X509_NAME_free(nm.x);
-    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+    X509_NAME_free(nm);
+    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
                                          local_sk_X509_NAME_ENTRY_pop_free);
     OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
     return 0;
@@ -288,20 +280,15 @@
 
 static int x509_name_encode(X509_NAME *a)
 {
-    union {
-        STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
-        ASN1_VALUE *a;
-    } intname = {
-        NULL
-    };
     int len;
     unsigned char *p;
     STACK_OF(X509_NAME_ENTRY) *entries = NULL;
     X509_NAME_ENTRY *entry;
     int set = -1;
     size_t i;
-    intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null();
-    if (!intname.s)
+    STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname =
+        sk_STACK_OF_X509_NAME_ENTRY_new_null();
+    if (!intname)
         goto memerr;
     for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
         entry = sk_X509_NAME_ENTRY_value(a->entries, i);
@@ -309,7 +296,7 @@
             entries = sk_X509_NAME_ENTRY_new_null();
             if (!entries)
                 goto memerr;
-            if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s, entries)) {
+            if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) {
                 sk_X509_NAME_ENTRY_free(entries);
                 goto memerr;
             }
@@ -318,19 +305,20 @@
         if (!sk_X509_NAME_ENTRY_push(entries, entry))
             goto memerr;
     }
-    len = ASN1_item_ex_i2d(&intname.a, NULL,
+    ASN1_VALUE *intname_val = (ASN1_VALUE *)intname;
+    len = ASN1_item_ex_i2d(&intname_val, NULL,
                            ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1);
     if (!BUF_MEM_grow(a->bytes, len))
         goto memerr;
     p = (unsigned char *)a->bytes->data;
-    ASN1_item_ex_i2d(&intname.a,
+    ASN1_item_ex_i2d(&intname_val,
                      &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1);
-    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
                                          local_sk_X509_NAME_ENTRY_free);
     a->modified = 0;
     return len;
  memerr:
-    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
                                          local_sk_X509_NAME_ENTRY_free);
     OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
     return -1;