Fix CRYPTO_dup_ex_data.

On malloc error, CRYPTO_set_ex_data may fail. (See upstream's
62f488d31733e5dc77b339f905b44f165550e47d.)

It also failed to copy the reserved slots when we revised the app-data
machinery, although this is unreachable as EC_KEY is the only thing
which uses this function and EC_KEY has no reserved slots. (We probably
can/should also take CRYPTO_dup_ex_data out of there, as it's a little
bit weird...)

Change-Id: I60bbc301f919d4c0ee7fff362f979f6ec18d73b7
Reviewed-on: https://boringssl-review.googlesource.com/14604
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/ex_data.c b/crypto/ex_data.c
index 5286513..20b762e 100644
--- a/crypto/ex_data.c
+++ b/crypto/ex_data.c
@@ -239,6 +239,13 @@
     return 1;
   }
 
+  for (size_t i = 0; i < ex_data_class->num_reserved; i++) {
+    void *ptr = CRYPTO_get_ex_data(from, i);
+    if (!CRYPTO_set_ex_data(to, i, ptr)) {
+      return 0;
+    }
+  }
+
   STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers;
   if (!get_func_pointers(&func_pointers, ex_data_class)) {
     return 0;
@@ -252,7 +259,10 @@
       func_pointer->dup_func(to, from, &ptr, i + ex_data_class->num_reserved,
                              func_pointer->argl, func_pointer->argp);
     }
-    CRYPTO_set_ex_data(to, i + ex_data_class->num_reserved, ptr);
+    if (!CRYPTO_set_ex_data(to, i + ex_data_class->num_reserved, ptr)) {
+      sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
+      return 0;
+    }
   }
 
   sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);