Use scopers in CBB_flush_asn1_set_of

One less `goto err`.

Change-Id: I64042c991ad9c2e12ca3d36c35911a2086bfcad4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/98728
Presubmit-BoringSSL-Verified: boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com <boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Lily Chen <chlily@google.com>
Commit-Queue: Lily Chen <chlily@google.com>
diff --git a/crypto/bytestring/cbb.cc b/crypto/bytestring/cbb.cc
index f8d1b5c..2289098 100644
--- a/crypto/bytestring/cbb.cc
+++ b/crypto/bytestring/cbb.cc
@@ -18,10 +18,13 @@
 #include <limits.h>
 #include <string.h>
 
+#include <algorithm>
+
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
 #include "../internal.h"
+#include "../mem_internal.h"
 #include "internal.h"
 
 
@@ -682,33 +685,13 @@
   return add_base128_integer(cbb, value);
 }
 
-static int compare_set_of_element(const void *a_ptr, const void *b_ptr) {
-  // See X.690, section 11.6 for the ordering. They are sorted in ascending
-  // order by their DER encoding.
-  const CBS *a = reinterpret_cast<const CBS *>(a_ptr),
-            *b = reinterpret_cast<const CBS *>(b_ptr);
-  size_t a_len = CBS_len(a), b_len = CBS_len(b);
-  size_t min_len = a_len < b_len ? a_len : b_len;
-  int ret = OPENSSL_memcmp(CBS_data(a), CBS_data(b), min_len);
-  if (ret != 0) {
-    return ret;
-  }
-  if (a_len == b_len) {
-    return 0;
-  }
-  // If one is a prefix of the other, the shorter one sorts first. (This is not
-  // actually reachable. No DER encoding is a prefix of another DER encoding.)
-  return a_len < b_len ? -1 : 1;
-}
-
 int CBB_flush_asn1_set_of(CBB *cbb) {
   if (!CBB_flush(cbb)) {
     return 0;
   }
 
-  CBS cbs;
   size_t num_children = 0;
-  CBS_init(&cbs, CBB_data(cbb), CBB_len(cbb));
+  CBS cbs(CBBAsSpan(cbb));
   while (CBS_len(&cbs) != 0) {
     if (!CBS_get_any_asn1_element(&cbs, nullptr, nullptr, nullptr)) {
       OPENSSL_PUT_ERROR(CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
@@ -723,39 +706,42 @@
 
   // Parse out the children and sort. We alias them into a copy of so they
   // remain valid as we rewrite `cbb`.
-  int ret = 0;
-  size_t buf_len = CBB_len(cbb);
-  uint8_t *buf =
-      reinterpret_cast<uint8_t *>(OPENSSL_memdup(CBB_data(cbb), buf_len));
-  CBS *children =
-      reinterpret_cast<CBS *>(OPENSSL_calloc(num_children, sizeof(CBS)));
-  uint8_t *out;
-  size_t offset = 0;
-  if (buf == nullptr || children == nullptr) {
-    goto err;
+  Array<uint8_t> copy;
+  Array<CBS> children;
+  if (!copy.CopyFrom(CBBAsSpan(cbb)) ||  //
+      !children.Init(num_children)) {
+    return 0;
   }
-  CBS_init(&cbs, buf, buf_len);
+  cbs = CBS(copy);
   for (size_t i = 0; i < num_children; i++) {
     if (!CBS_get_any_asn1_element(&cbs, &children[i], nullptr, nullptr)) {
-      goto err;
+      OPENSSL_PUT_ERROR(CRYPTO, ERR_R_INTERNAL_ERROR);
+      return 0;
     }
   }
-  qsort(children, num_children, sizeof(CBS), compare_set_of_element);
+  std::sort(children.begin(), children.end(), [](CBS a, CBS b) -> bool {
+    // See X.690, section 11.6 for the ordering. They are sorted in ascending
+    // order by their DER encoding. First compare the common prefix.
+    size_t a_len = CBS_len(&a), b_len = CBS_len(&b);
+    int cmp =
+        OPENSSL_memcmp(CBS_data(&a), CBS_data(&b), std::min(a_len, b_len));
+    if (cmp != 0) {
+      return cmp < 0;
+    }
+    // If one is a prefix of the other, the shorter one sorts first. (They're
+    // actually always equal length. DER encodings are prefix-free.)
+    return a_len < b_len;
+  });
 
   // Write the contents back in the new order.
-  out = (uint8_t *)CBB_data(cbb);
+  uint8_t *out = const_cast<uint8_t *>(CBB_data(cbb));
+  size_t offset = 0;
   for (size_t i = 0; i < num_children; i++) {
     OPENSSL_memcpy(out + offset, CBS_data(&children[i]), CBS_len(&children[i]));
     offset += CBS_len(&children[i]);
   }
-  assert(offset == buf_len);
-
-  ret = 1;
-
-err:
-  OPENSSL_free(buf);
-  OPENSSL_free(children);
-  return ret;
+  assert(offset == copy.size());
+  return 1;
 }
 
 bool bssl::CBBFinishArray(CBB *cbb, Array<uint8_t> *out) {