Have |CBB_init| zero the |CBB| before any possible failures.

People expect to do:

CBB foo;

if (!CBB_init(&foo, 100) ||
    …
    …) {
  CBB_cleanup(&foo);
  return 0;
}

However, currently, if the allocation of |initial_capacity| fails in
|CBB_init| then |CBB_cleanup| will operate on uninitialised values. This
change makes the above pattern safe.

Change-Id: I3e002fda8f0a3ac18650b504e7e84a842d4165ca
Reviewed-on: https://boringssl-review.googlesource.com/6495
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/bytestring/bytestring_test.cc b/crypto/bytestring/bytestring_test.cc
index f25c186..4c2add6 100644
--- a/crypto/bytestring/bytestring_test.cc
+++ b/crypto/bytestring/bytestring_test.cc
@@ -316,6 +316,22 @@
   return true;
 }
 
+static bool TestCBBAllocFailure() {
+  CBB cbb;
+  memset(&cbb, 0x42, sizeof(cbb));
+
+  if (CBB_init(&cbb, (size_t)-1)) {
+    fprintf(stderr, "Excessive allocation successful!\n");
+    CBB_cleanup(&cbb);
+    return false;
+  }
+
+  /* |CBB_init| should have cleared |cbb| before failing therefore this should
+   * not crash. */
+  CBB_cleanup(&cbb);
+  return true;
+}
+
 static bool TestCBBFinishChild() {
   CBB cbb, child;
   uint8_t *out_buf;
@@ -716,6 +732,7 @@
       !TestGetASN1() ||
       !TestCBBBasic() ||
       !TestCBBFixed() ||
+      !TestCBBAllocFailure() ||
       !TestCBBFinishChild() ||
       !TestCBBMisuse() ||
       !TestCBBPrefixed() ||
diff --git a/crypto/bytestring/cbb.c b/crypto/bytestring/cbb.c
index 434ec13..74573c9 100644
--- a/crypto/bytestring/cbb.c
+++ b/crypto/bytestring/cbb.c
@@ -25,6 +25,7 @@
 }
 
 static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
+  /* This assumes that |cbb| has already been zeroed. */
   struct cbb_buffer_st *base;
 
   base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
@@ -37,16 +38,15 @@
   base->cap = cap;
   base->can_resize = 1;
 
-  memset(cbb, 0, sizeof(CBB));
   cbb->base = base;
   cbb->is_top_level = 1;
   return 1;
 }
 
 int CBB_init(CBB *cbb, size_t initial_capacity) {
-  uint8_t *buf;
+  CBB_zero(cbb);
 
-  buf = OPENSSL_malloc(initial_capacity);
+  uint8_t *buf = OPENSSL_malloc(initial_capacity);
   if (initial_capacity > 0 && buf == NULL) {
     return 0;
   }
@@ -60,6 +60,8 @@
 }
 
 int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
+  CBB_zero(cbb);
+
   if (!cbb_init(cbb, buf, len)) {
     return 0;
   }