Remove a pointer indirection in STACK_OF(T) comparisons At the public API, the comparison functions are a double pointer to match qsort. qsort comparators are passed pointers to the list elements, and our list elements are T*. qsort needs this indirection because it can sort values of arbitrary size. However, our type-erased versions have no such constraints. Since we know our all elements are pointers, we can skip the indirection. Change-Id: Ibb102b51a5aaf0a68a7318bf14ec8f4f9c7a3daf Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60506 Reviewed-by: Bob Beck <bbe@google.com> Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/stack/stack.c b/crypto/stack/stack.c index 4f4f1df..a11533e 100644 --- a/crypto/stack/stack.c +++ b/crypto/stack/stack.c
@@ -297,8 +297,7 @@ if (!OPENSSL_sk_is_sorted(sk)) { for (size_t i = 0; i < sk->num; i++) { - const void *elem = sk->data[i]; - if (call_cmp_func(sk->comp, &p, &elem) == 0) { + if (call_cmp_func(sk->comp, p, sk->data[i]) == 0) { if (out_index) { *out_index = i; } @@ -317,8 +316,7 @@ // Bias |mid| towards |lo|. See the |r == 0| case below. size_t mid = lo + (hi - lo - 1) / 2; assert(lo <= mid && mid < hi); - const void *elem = sk->data[mid]; - int r = call_cmp_func(sk->comp, &p, &elem); + int r = call_cmp_func(sk->comp, p, sk->data[mid]); if (r > 0) { lo = mid + 1; // |mid| is too low. } else if (r < 0) { @@ -403,7 +401,10 @@ static int sort_compare(void *ctx_v, const void *a, const void *b) { struct sort_compare_ctx *ctx = ctx_v; - return ctx->call_cmp_func(ctx->cmp_func, a, b); + // |a| and |b| point to |void*| pointers which contain the actual values. + const void *const *a_ptr = a; + const void *const *b_ptr = b; + return ctx->call_cmp_func(ctx->cmp_func, *a_ptr, *b_ptr); } #endif
diff --git a/include/openssl/stack.h b/include/openssl/stack.h index ce92be6..7d5d4d7 100644 --- a/include/openssl/stack.h +++ b/include/openssl/stack.h
@@ -279,9 +279,8 @@ // true types. typedef void (*OPENSSL_sk_call_free_func)(OPENSSL_sk_free_func, void *); typedef void *(*OPENSSL_sk_call_copy_func)(OPENSSL_sk_copy_func, const void *); -typedef int (*OPENSSL_sk_call_cmp_func)(OPENSSL_sk_cmp_func, - const void *const *, - const void *const *); +typedef int (*OPENSSL_sk_call_cmp_func)(OPENSSL_sk_cmp_func, const void *, + const void *); typedef int (*OPENSSL_sk_call_delete_if_func)(OPENSSL_sk_delete_if_func, void *, void *); @@ -421,13 +420,10 @@ } \ \ OPENSSL_INLINE int sk_##name##_call_cmp_func(OPENSSL_sk_cmp_func cmp_func, \ - const void *const *a, \ - const void *const *b) { \ - /* The data is actually stored as |void*| pointers, so read the pointer \ - * as |void*| and then pass the corrected type into the caller-supplied \ - * function, which expects |constptrtype*|. */ \ - constptrtype a_ptr = (constptrtype)*a; \ - constptrtype b_ptr = (constptrtype)*b; \ + const void *a, const void *b) { \ + constptrtype a_ptr = (constptrtype)a; \ + constptrtype b_ptr = (constptrtype)b; \ + /* |cmp_func| expects an extra layer of pointers to match qsort. */ \ return ((sk_##name##_cmp_func)cmp_func)(&a_ptr, &b_ptr); \ } \ \