CBB_cleanup: null out the buffer pointer if it was freed.

This should make ScopedCBB safe in conjunction with CBB_cleanup calls
(e.g. in CBB_finish_i2d).

Change-Id: Ib0cd8b5ec715cebd6c8171930e383d7b6a6a6964
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/95647
Commit-Queue: Rudolf Polzer <rpolzer@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/bytestring/asn1_compat.cc b/crypto/bytestring/asn1_compat.cc
index 0ce6055..21ebde9 100644
--- a/crypto/bytestring/asn1_compat.cc
+++ b/crypto/bytestring/asn1_compat.cc
@@ -34,7 +34,6 @@
   uint8_t *der;
   size_t der_len;
   if (!CBB_finish(cbb, &der, &der_len)) {
-    CBB_cleanup(cbb);
     return -1;
   }
   if (der_len > INT_MAX) {
diff --git a/crypto/bytestring/bytestring_test.cc b/crypto/bytestring/bytestring_test.cc
index e0c200d..e67ffa8 100644
--- a/crypto/bytestring/bytestring_test.cc
+++ b/crypto/bytestring/bytestring_test.cc
@@ -1301,6 +1301,14 @@
   CBB_cleanup(&cbb);
 }
 
+TEST(CBBTest, ScopedCBBCleanup) {
+  // It is valid to |CBB_cleanup| a |ScopedCBB|.
+  ScopedCBB cbb;
+  ASSERT_TRUE(CBB_init(cbb.get(), 32));
+  CBB_cleanup(cbb.get());
+  // ASAN should not detect a double free here.
+}
+
 TEST(CBBTest, Reserve) {
   uint8_t buf[10];
   uint8_t *ptr;
diff --git a/crypto/bytestring/cbb.cc b/crypto/bytestring/cbb.cc
index bbe59fa..fed8d76 100644
--- a/crypto/bytestring/cbb.cc
+++ b/crypto/bytestring/cbb.cc
@@ -67,6 +67,7 @@
 
   if (cbb->u.base.can_resize) {
     OPENSSL_free(cbb->u.base.buf);
+    cbb->u.base.buf = nullptr;
   }
 }
 
diff --git a/crypto/bytestring/internal.h b/crypto/bytestring/internal.h
index 35bd4c9..25a50f3 100644
--- a/crypto/bytestring/internal.h
+++ b/crypto/bytestring/internal.h
@@ -64,8 +64,7 @@
 // CBB_finish_i2d calls |CBB_finish| on |cbb| which must have been initialized
 // with |CBB_init|. If |outp| is not NULL then the result is written to |*outp|
 // and |*outp| is advanced just past the output. It returns the number of bytes
-// in the result, whether written or not, or a negative value on error. On
-// error, it calls |CBB_cleanup| on |cbb|.
+// in the result, whether written or not, or a negative value on error.
 //
 // This function may be used to help implement legacy i2d ASN.1 functions.
 OPENSSL_EXPORT int CBB_finish_i2d(CBB *cbb, uint8_t **outp);