stack: fix searching when the stack isn't sorted.

More specifically, don't sort the stack when searching when it isn't sorted.
This avoids a race condition.

Fixes #20135

Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20782)
This commit is contained in:
Pauli 2023-04-20 16:04:10 +10:00 committed by Tomas Mraz
parent 4df13d1054
commit eb0935fd21

View File

@ -315,39 +315,54 @@ void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc)
}
static int internal_find(OPENSSL_STACK *st, const void *data,
int ret_val_options, int *pnum)
int ret_val_options, int *pnum_matched)
{
const void *r;
int i;
int i, count = 0;
int *pnum = pnum_matched;
if (st == NULL || st->num == 0)
return -1;
if (pnum == NULL)
pnum = &count;
if (st->comp == NULL) {
for (i = 0; i < st->num; i++)
if (st->data[i] == data) {
if (pnum != NULL)
*pnum = 1;
*pnum = 1;
return i;
}
if (pnum != NULL)
*pnum = 0;
*pnum = 0;
return -1;
}
if (!st->sorted) {
if (st->num > 1)
qsort(st->data, st->num, sizeof(void *), st->comp);
st->sorted = 1; /* empty or single-element stack is considered sorted */
}
if (data == NULL)
return -1;
if (pnum != NULL)
if (!st->sorted) {
int res = -1;
for (i = 0; i < st->num; i++)
if (st->comp(&data, st->data + i) == 0) {
if (res == -1)
res = i;
++*pnum;
/* Check if only one result is wanted and exit if so */
if (pnum_matched == NULL)
return i;
}
if (res == -1)
*pnum = 0;
return res;
}
if (pnum_matched != NULL)
ret_val_options |= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH;
r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp,
ret_val_options);
if (pnum != NULL) {
if (pnum_matched != NULL) {
*pnum = 0;
if (r != NULL) {
const void **p = (const void **)r;