Add a bssl::PushToStack helper.

Pushing entries onto a stack when handling malloc failures is a
nuisance. sk_push only takes ownership on success. PushToStack smooths
that over with a UniquePtr.

Bug: 132
Change-Id: I4f0a9eee86dda7453f128c33d3a71b550beb25e9
Reviewed-on: https://boringssl-review.googlesource.com/18468
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/include/openssl/stack.h b/include/openssl/stack.h
index 0e59d6a..3626fb0 100644
--- a/include/openssl/stack.h
+++ b/include/openssl/stack.h
@@ -450,6 +450,21 @@
 
 }  // namespace internal
 
+// PushToStack pushes |elem| to |sk|. It returns true on success and false on
+// allocation failure.
+template <typename Stack>
+static inline
+    typename std::enable_if<!internal::StackTraits<Stack>::kIsConst, bool>::type
+    PushToStack(Stack *sk,
+                UniquePtr<typename internal::StackTraits<Stack>::Type> elem) {
+  if (!sk_push(reinterpret_cast<_STACK *>(sk), elem.get())) {
+    return false;
+  }
+  // sk_push takes ownership on success.
+  elem.release();
+  return true;
+}
+
 }  // namespace bssl
 
 // Define begin() and end() for stack types so C++ range for loops work.
diff --git a/ssl/tls13_both.cc b/ssl/tls13_both.cc
index 627f038..a5b9c53 100644
--- a/ssl/tls13_both.cc
+++ b/ssl/tls13_both.cc
@@ -245,11 +245,10 @@
       }
     }
 
-    CRYPTO_BUFFER *buf =
-        CRYPTO_BUFFER_new_from_CBS(&certificate, ssl->ctx->pool);
-    if (buf == NULL ||
-        !sk_CRYPTO_BUFFER_push(certs.get(), buf)) {
-      CRYPTO_BUFFER_free(buf);
+    UniquePtr<CRYPTO_BUFFER> buf(
+        CRYPTO_BUFFER_new_from_CBS(&certificate, ssl->ctx->pool));
+    if (!buf ||
+        !PushToStack(certs.get(), std::move(buf))) {
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       return 0;