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) {