1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 12e1051a39Sopenharmony_ci#include "internal/numbers.h" 13e1051a39Sopenharmony_ci#include <openssl/stack.h> 14e1051a39Sopenharmony_ci#include <errno.h> 15e1051a39Sopenharmony_ci#include <openssl/e_os2.h> /* For ossl_inline */ 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_ci/* 18e1051a39Sopenharmony_ci * The initial number of nodes in the array. 19e1051a39Sopenharmony_ci */ 20e1051a39Sopenharmony_cistatic const int min_nodes = 4; 21e1051a39Sopenharmony_cistatic const int max_nodes = SIZE_MAX / sizeof(void *) < INT_MAX 22e1051a39Sopenharmony_ci ? (int)(SIZE_MAX / sizeof(void *)) : INT_MAX; 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_cistruct stack_st { 25e1051a39Sopenharmony_ci int num; 26e1051a39Sopenharmony_ci const void **data; 27e1051a39Sopenharmony_ci int sorted; 28e1051a39Sopenharmony_ci int num_alloc; 29e1051a39Sopenharmony_ci OPENSSL_sk_compfunc comp; 30e1051a39Sopenharmony_ci}; 31e1051a39Sopenharmony_ci 32e1051a39Sopenharmony_ciOPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, 33e1051a39Sopenharmony_ci OPENSSL_sk_compfunc c) 34e1051a39Sopenharmony_ci{ 35e1051a39Sopenharmony_ci OPENSSL_sk_compfunc old = sk->comp; 36e1051a39Sopenharmony_ci 37e1051a39Sopenharmony_ci if (sk->comp != c) 38e1051a39Sopenharmony_ci sk->sorted = 0; 39e1051a39Sopenharmony_ci sk->comp = c; 40e1051a39Sopenharmony_ci 41e1051a39Sopenharmony_ci return old; 42e1051a39Sopenharmony_ci} 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_ciOPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk) 45e1051a39Sopenharmony_ci{ 46e1051a39Sopenharmony_ci OPENSSL_STACK *ret; 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ci if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) 49e1051a39Sopenharmony_ci goto err; 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_ci if (sk == NULL) { 52e1051a39Sopenharmony_ci ret->num = 0; 53e1051a39Sopenharmony_ci ret->sorted = 0; 54e1051a39Sopenharmony_ci ret->comp = NULL; 55e1051a39Sopenharmony_ci } else { 56e1051a39Sopenharmony_ci /* direct structure assignment */ 57e1051a39Sopenharmony_ci *ret = *sk; 58e1051a39Sopenharmony_ci } 59e1051a39Sopenharmony_ci 60e1051a39Sopenharmony_ci if (sk == NULL || sk->num == 0) { 61e1051a39Sopenharmony_ci /* postpone |ret->data| allocation */ 62e1051a39Sopenharmony_ci ret->data = NULL; 63e1051a39Sopenharmony_ci ret->num_alloc = 0; 64e1051a39Sopenharmony_ci return ret; 65e1051a39Sopenharmony_ci } 66e1051a39Sopenharmony_ci 67e1051a39Sopenharmony_ci /* duplicate |sk->data| content */ 68e1051a39Sopenharmony_ci ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc); 69e1051a39Sopenharmony_ci if (ret->data == NULL) 70e1051a39Sopenharmony_ci goto err; 71e1051a39Sopenharmony_ci memcpy(ret->data, sk->data, sizeof(void *) * sk->num); 72e1051a39Sopenharmony_ci return ret; 73e1051a39Sopenharmony_ci 74e1051a39Sopenharmony_ci err: 75e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 76e1051a39Sopenharmony_ci OPENSSL_sk_free(ret); 77e1051a39Sopenharmony_ci return NULL; 78e1051a39Sopenharmony_ci} 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_ciOPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk, 81e1051a39Sopenharmony_ci OPENSSL_sk_copyfunc copy_func, 82e1051a39Sopenharmony_ci OPENSSL_sk_freefunc free_func) 83e1051a39Sopenharmony_ci{ 84e1051a39Sopenharmony_ci OPENSSL_STACK *ret; 85e1051a39Sopenharmony_ci int i; 86e1051a39Sopenharmony_ci 87e1051a39Sopenharmony_ci if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) 88e1051a39Sopenharmony_ci goto err; 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ci if (sk == NULL) { 91e1051a39Sopenharmony_ci ret->num = 0; 92e1051a39Sopenharmony_ci ret->sorted = 0; 93e1051a39Sopenharmony_ci ret->comp = NULL; 94e1051a39Sopenharmony_ci } else { 95e1051a39Sopenharmony_ci /* direct structure assignment */ 96e1051a39Sopenharmony_ci *ret = *sk; 97e1051a39Sopenharmony_ci } 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci if (sk == NULL || sk->num == 0) { 100e1051a39Sopenharmony_ci /* postpone |ret| data allocation */ 101e1051a39Sopenharmony_ci ret->data = NULL; 102e1051a39Sopenharmony_ci ret->num_alloc = 0; 103e1051a39Sopenharmony_ci return ret; 104e1051a39Sopenharmony_ci } 105e1051a39Sopenharmony_ci 106e1051a39Sopenharmony_ci ret->num_alloc = sk->num > min_nodes ? sk->num : min_nodes; 107e1051a39Sopenharmony_ci ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc); 108e1051a39Sopenharmony_ci if (ret->data == NULL) 109e1051a39Sopenharmony_ci goto err; 110e1051a39Sopenharmony_ci 111e1051a39Sopenharmony_ci for (i = 0; i < ret->num; ++i) { 112e1051a39Sopenharmony_ci if (sk->data[i] == NULL) 113e1051a39Sopenharmony_ci continue; 114e1051a39Sopenharmony_ci if ((ret->data[i] = copy_func(sk->data[i])) == NULL) { 115e1051a39Sopenharmony_ci while (--i >= 0) 116e1051a39Sopenharmony_ci if (ret->data[i] != NULL) 117e1051a39Sopenharmony_ci free_func((void *)ret->data[i]); 118e1051a39Sopenharmony_ci goto err; 119e1051a39Sopenharmony_ci } 120e1051a39Sopenharmony_ci } 121e1051a39Sopenharmony_ci return ret; 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ci err: 124e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 125e1051a39Sopenharmony_ci OPENSSL_sk_free(ret); 126e1051a39Sopenharmony_ci return NULL; 127e1051a39Sopenharmony_ci} 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_ciOPENSSL_STACK *OPENSSL_sk_new_null(void) 130e1051a39Sopenharmony_ci{ 131e1051a39Sopenharmony_ci return OPENSSL_sk_new_reserve(NULL, 0); 132e1051a39Sopenharmony_ci} 133e1051a39Sopenharmony_ci 134e1051a39Sopenharmony_ciOPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c) 135e1051a39Sopenharmony_ci{ 136e1051a39Sopenharmony_ci return OPENSSL_sk_new_reserve(c, 0); 137e1051a39Sopenharmony_ci} 138e1051a39Sopenharmony_ci 139e1051a39Sopenharmony_ci/* 140e1051a39Sopenharmony_ci * Calculate the array growth based on the target size. 141e1051a39Sopenharmony_ci * 142e1051a39Sopenharmony_ci * The growth fraction is a rational number and is defined by a numerator 143e1051a39Sopenharmony_ci * and a denominator. According to Andrew Koenig in his paper "Why Are 144e1051a39Sopenharmony_ci * Vectors Efficient?" from JOOP 11(5) 1998, this factor should be less 145e1051a39Sopenharmony_ci * than the golden ratio (1.618...). 146e1051a39Sopenharmony_ci * 147e1051a39Sopenharmony_ci * We use 3/2 = 1.5 for simplicity of calculation and overflow checking. 148e1051a39Sopenharmony_ci * Another option 8/5 = 1.6 allows for slightly faster growth, although safe 149e1051a39Sopenharmony_ci * computation is more difficult. 150e1051a39Sopenharmony_ci * 151e1051a39Sopenharmony_ci * The limit to avoid overflow is spot on. The modulo three correction term 152e1051a39Sopenharmony_ci * ensures that the limit is the largest number than can be expanded by the 153e1051a39Sopenharmony_ci * growth factor without exceeding the hard limit. 154e1051a39Sopenharmony_ci * 155e1051a39Sopenharmony_ci * Do not call it with |current| lower than 2, or it will infinitely loop. 156e1051a39Sopenharmony_ci */ 157e1051a39Sopenharmony_cistatic ossl_inline int compute_growth(int target, int current) 158e1051a39Sopenharmony_ci{ 159e1051a39Sopenharmony_ci const int limit = (max_nodes / 3) * 2 + (max_nodes % 3 ? 1 : 0); 160e1051a39Sopenharmony_ci 161e1051a39Sopenharmony_ci while (current < target) { 162e1051a39Sopenharmony_ci /* Check to see if we're at the hard limit */ 163e1051a39Sopenharmony_ci if (current >= max_nodes) 164e1051a39Sopenharmony_ci return 0; 165e1051a39Sopenharmony_ci 166e1051a39Sopenharmony_ci /* Expand the size by a factor of 3/2 if it is within range */ 167e1051a39Sopenharmony_ci current = current < limit ? current + current / 2 : max_nodes; 168e1051a39Sopenharmony_ci } 169e1051a39Sopenharmony_ci return current; 170e1051a39Sopenharmony_ci} 171e1051a39Sopenharmony_ci 172e1051a39Sopenharmony_ci/* internal STACK storage allocation */ 173e1051a39Sopenharmony_cistatic int sk_reserve(OPENSSL_STACK *st, int n, int exact) 174e1051a39Sopenharmony_ci{ 175e1051a39Sopenharmony_ci const void **tmpdata; 176e1051a39Sopenharmony_ci int num_alloc; 177e1051a39Sopenharmony_ci 178e1051a39Sopenharmony_ci /* Check to see the reservation isn't exceeding the hard limit */ 179e1051a39Sopenharmony_ci if (n > max_nodes - st->num) { 180e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS); 181e1051a39Sopenharmony_ci return 0; 182e1051a39Sopenharmony_ci } 183e1051a39Sopenharmony_ci 184e1051a39Sopenharmony_ci /* Figure out the new size */ 185e1051a39Sopenharmony_ci num_alloc = st->num + n; 186e1051a39Sopenharmony_ci if (num_alloc < min_nodes) 187e1051a39Sopenharmony_ci num_alloc = min_nodes; 188e1051a39Sopenharmony_ci 189e1051a39Sopenharmony_ci /* If |st->data| allocation was postponed */ 190e1051a39Sopenharmony_ci if (st->data == NULL) { 191e1051a39Sopenharmony_ci /* 192e1051a39Sopenharmony_ci * At this point, |st->num_alloc| and |st->num| are 0; 193e1051a39Sopenharmony_ci * so |num_alloc| value is |n| or |min_nodes| if greater than |n|. 194e1051a39Sopenharmony_ci */ 195e1051a39Sopenharmony_ci if ((st->data = OPENSSL_zalloc(sizeof(void *) * num_alloc)) == NULL) { 196e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 197e1051a39Sopenharmony_ci return 0; 198e1051a39Sopenharmony_ci } 199e1051a39Sopenharmony_ci st->num_alloc = num_alloc; 200e1051a39Sopenharmony_ci return 1; 201e1051a39Sopenharmony_ci } 202e1051a39Sopenharmony_ci 203e1051a39Sopenharmony_ci if (!exact) { 204e1051a39Sopenharmony_ci if (num_alloc <= st->num_alloc) 205e1051a39Sopenharmony_ci return 1; 206e1051a39Sopenharmony_ci num_alloc = compute_growth(num_alloc, st->num_alloc); 207e1051a39Sopenharmony_ci if (num_alloc == 0) { 208e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS); 209e1051a39Sopenharmony_ci return 0; 210e1051a39Sopenharmony_ci } 211e1051a39Sopenharmony_ci } else if (num_alloc == st->num_alloc) { 212e1051a39Sopenharmony_ci return 1; 213e1051a39Sopenharmony_ci } 214e1051a39Sopenharmony_ci 215e1051a39Sopenharmony_ci tmpdata = OPENSSL_realloc((void *)st->data, sizeof(void *) * num_alloc); 216e1051a39Sopenharmony_ci if (tmpdata == NULL) { 217e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 218e1051a39Sopenharmony_ci return 0; 219e1051a39Sopenharmony_ci } 220e1051a39Sopenharmony_ci 221e1051a39Sopenharmony_ci st->data = tmpdata; 222e1051a39Sopenharmony_ci st->num_alloc = num_alloc; 223e1051a39Sopenharmony_ci return 1; 224e1051a39Sopenharmony_ci} 225e1051a39Sopenharmony_ci 226e1051a39Sopenharmony_ciOPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n) 227e1051a39Sopenharmony_ci{ 228e1051a39Sopenharmony_ci OPENSSL_STACK *st = OPENSSL_zalloc(sizeof(OPENSSL_STACK)); 229e1051a39Sopenharmony_ci 230e1051a39Sopenharmony_ci if (st == NULL) { 231e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 232e1051a39Sopenharmony_ci return NULL; 233e1051a39Sopenharmony_ci } 234e1051a39Sopenharmony_ci 235e1051a39Sopenharmony_ci st->comp = c; 236e1051a39Sopenharmony_ci 237e1051a39Sopenharmony_ci if (n <= 0) 238e1051a39Sopenharmony_ci return st; 239e1051a39Sopenharmony_ci 240e1051a39Sopenharmony_ci if (!sk_reserve(st, n, 1)) { 241e1051a39Sopenharmony_ci OPENSSL_sk_free(st); 242e1051a39Sopenharmony_ci return NULL; 243e1051a39Sopenharmony_ci } 244e1051a39Sopenharmony_ci 245e1051a39Sopenharmony_ci return st; 246e1051a39Sopenharmony_ci} 247e1051a39Sopenharmony_ci 248e1051a39Sopenharmony_ciint OPENSSL_sk_reserve(OPENSSL_STACK *st, int n) 249e1051a39Sopenharmony_ci{ 250e1051a39Sopenharmony_ci if (st == NULL) { 251e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); 252e1051a39Sopenharmony_ci return 0; 253e1051a39Sopenharmony_ci } 254e1051a39Sopenharmony_ci 255e1051a39Sopenharmony_ci if (n < 0) 256e1051a39Sopenharmony_ci return 1; 257e1051a39Sopenharmony_ci return sk_reserve(st, n, 1); 258e1051a39Sopenharmony_ci} 259e1051a39Sopenharmony_ci 260e1051a39Sopenharmony_ciint OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc) 261e1051a39Sopenharmony_ci{ 262e1051a39Sopenharmony_ci if (st == NULL) { 263e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); 264e1051a39Sopenharmony_ci return 0; 265e1051a39Sopenharmony_ci } 266e1051a39Sopenharmony_ci if (st->num == max_nodes) { 267e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS); 268e1051a39Sopenharmony_ci return 0; 269e1051a39Sopenharmony_ci } 270e1051a39Sopenharmony_ci 271e1051a39Sopenharmony_ci if (!sk_reserve(st, 1, 0)) 272e1051a39Sopenharmony_ci return 0; 273e1051a39Sopenharmony_ci 274e1051a39Sopenharmony_ci if ((loc >= st->num) || (loc < 0)) { 275e1051a39Sopenharmony_ci st->data[st->num] = data; 276e1051a39Sopenharmony_ci } else { 277e1051a39Sopenharmony_ci memmove(&st->data[loc + 1], &st->data[loc], 278e1051a39Sopenharmony_ci sizeof(st->data[0]) * (st->num - loc)); 279e1051a39Sopenharmony_ci st->data[loc] = data; 280e1051a39Sopenharmony_ci } 281e1051a39Sopenharmony_ci st->num++; 282e1051a39Sopenharmony_ci st->sorted = 0; 283e1051a39Sopenharmony_ci return st->num; 284e1051a39Sopenharmony_ci} 285e1051a39Sopenharmony_ci 286e1051a39Sopenharmony_cistatic ossl_inline void *internal_delete(OPENSSL_STACK *st, int loc) 287e1051a39Sopenharmony_ci{ 288e1051a39Sopenharmony_ci const void *ret = st->data[loc]; 289e1051a39Sopenharmony_ci 290e1051a39Sopenharmony_ci if (loc != st->num - 1) 291e1051a39Sopenharmony_ci memmove(&st->data[loc], &st->data[loc + 1], 292e1051a39Sopenharmony_ci sizeof(st->data[0]) * (st->num - loc - 1)); 293e1051a39Sopenharmony_ci st->num--; 294e1051a39Sopenharmony_ci 295e1051a39Sopenharmony_ci return (void *)ret; 296e1051a39Sopenharmony_ci} 297e1051a39Sopenharmony_ci 298e1051a39Sopenharmony_civoid *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p) 299e1051a39Sopenharmony_ci{ 300e1051a39Sopenharmony_ci int i; 301e1051a39Sopenharmony_ci 302e1051a39Sopenharmony_ci if (st == NULL) 303e1051a39Sopenharmony_ci return NULL; 304e1051a39Sopenharmony_ci 305e1051a39Sopenharmony_ci for (i = 0; i < st->num; i++) 306e1051a39Sopenharmony_ci if (st->data[i] == p) 307e1051a39Sopenharmony_ci return internal_delete(st, i); 308e1051a39Sopenharmony_ci return NULL; 309e1051a39Sopenharmony_ci} 310e1051a39Sopenharmony_ci 311e1051a39Sopenharmony_civoid *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc) 312e1051a39Sopenharmony_ci{ 313e1051a39Sopenharmony_ci if (st == NULL || loc < 0 || loc >= st->num) 314e1051a39Sopenharmony_ci return NULL; 315e1051a39Sopenharmony_ci 316e1051a39Sopenharmony_ci return internal_delete(st, loc); 317e1051a39Sopenharmony_ci} 318e1051a39Sopenharmony_ci 319e1051a39Sopenharmony_cistatic int internal_find(OPENSSL_STACK *st, const void *data, 320e1051a39Sopenharmony_ci int ret_val_options, int *pnum) 321e1051a39Sopenharmony_ci{ 322e1051a39Sopenharmony_ci const void *r; 323e1051a39Sopenharmony_ci int i; 324e1051a39Sopenharmony_ci 325e1051a39Sopenharmony_ci if (st == NULL || st->num == 0) 326e1051a39Sopenharmony_ci return -1; 327e1051a39Sopenharmony_ci 328e1051a39Sopenharmony_ci if (st->comp == NULL) { 329e1051a39Sopenharmony_ci for (i = 0; i < st->num; i++) 330e1051a39Sopenharmony_ci if (st->data[i] == data) { 331e1051a39Sopenharmony_ci if (pnum != NULL) 332e1051a39Sopenharmony_ci *pnum = 1; 333e1051a39Sopenharmony_ci return i; 334e1051a39Sopenharmony_ci } 335e1051a39Sopenharmony_ci if (pnum != NULL) 336e1051a39Sopenharmony_ci *pnum = 0; 337e1051a39Sopenharmony_ci return -1; 338e1051a39Sopenharmony_ci } 339e1051a39Sopenharmony_ci 340e1051a39Sopenharmony_ci if (!st->sorted) { 341e1051a39Sopenharmony_ci if (st->num > 1) 342e1051a39Sopenharmony_ci qsort(st->data, st->num, sizeof(void *), st->comp); 343e1051a39Sopenharmony_ci st->sorted = 1; /* empty or single-element stack is considered sorted */ 344e1051a39Sopenharmony_ci } 345e1051a39Sopenharmony_ci if (data == NULL) 346e1051a39Sopenharmony_ci return -1; 347e1051a39Sopenharmony_ci if (pnum != NULL) 348e1051a39Sopenharmony_ci ret_val_options |= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH; 349e1051a39Sopenharmony_ci r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp, 350e1051a39Sopenharmony_ci ret_val_options); 351e1051a39Sopenharmony_ci 352e1051a39Sopenharmony_ci if (pnum != NULL) { 353e1051a39Sopenharmony_ci *pnum = 0; 354e1051a39Sopenharmony_ci if (r != NULL) { 355e1051a39Sopenharmony_ci const void **p = (const void **)r; 356e1051a39Sopenharmony_ci 357e1051a39Sopenharmony_ci while (p < st->data + st->num) { 358e1051a39Sopenharmony_ci if (st->comp(&data, p) != 0) 359e1051a39Sopenharmony_ci break; 360e1051a39Sopenharmony_ci ++*pnum; 361e1051a39Sopenharmony_ci ++p; 362e1051a39Sopenharmony_ci } 363e1051a39Sopenharmony_ci } 364e1051a39Sopenharmony_ci } 365e1051a39Sopenharmony_ci 366e1051a39Sopenharmony_ci return r == NULL ? -1 : (int)((const void **)r - st->data); 367e1051a39Sopenharmony_ci} 368e1051a39Sopenharmony_ci 369e1051a39Sopenharmony_ciint OPENSSL_sk_find(OPENSSL_STACK *st, const void *data) 370e1051a39Sopenharmony_ci{ 371e1051a39Sopenharmony_ci return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, NULL); 372e1051a39Sopenharmony_ci} 373e1051a39Sopenharmony_ci 374e1051a39Sopenharmony_ciint OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data) 375e1051a39Sopenharmony_ci{ 376e1051a39Sopenharmony_ci return internal_find(st, data, OSSL_BSEARCH_VALUE_ON_NOMATCH, NULL); 377e1051a39Sopenharmony_ci} 378e1051a39Sopenharmony_ci 379e1051a39Sopenharmony_ciint OPENSSL_sk_find_all(OPENSSL_STACK *st, const void *data, int *pnum) 380e1051a39Sopenharmony_ci{ 381e1051a39Sopenharmony_ci return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, pnum); 382e1051a39Sopenharmony_ci} 383e1051a39Sopenharmony_ci 384e1051a39Sopenharmony_ciint OPENSSL_sk_push(OPENSSL_STACK *st, const void *data) 385e1051a39Sopenharmony_ci{ 386e1051a39Sopenharmony_ci if (st == NULL) 387e1051a39Sopenharmony_ci return -1; 388e1051a39Sopenharmony_ci return OPENSSL_sk_insert(st, data, st->num); 389e1051a39Sopenharmony_ci} 390e1051a39Sopenharmony_ci 391e1051a39Sopenharmony_ciint OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data) 392e1051a39Sopenharmony_ci{ 393e1051a39Sopenharmony_ci return OPENSSL_sk_insert(st, data, 0); 394e1051a39Sopenharmony_ci} 395e1051a39Sopenharmony_ci 396e1051a39Sopenharmony_civoid *OPENSSL_sk_shift(OPENSSL_STACK *st) 397e1051a39Sopenharmony_ci{ 398e1051a39Sopenharmony_ci if (st == NULL || st->num == 0) 399e1051a39Sopenharmony_ci return NULL; 400e1051a39Sopenharmony_ci return internal_delete(st, 0); 401e1051a39Sopenharmony_ci} 402e1051a39Sopenharmony_ci 403e1051a39Sopenharmony_civoid *OPENSSL_sk_pop(OPENSSL_STACK *st) 404e1051a39Sopenharmony_ci{ 405e1051a39Sopenharmony_ci if (st == NULL || st->num == 0) 406e1051a39Sopenharmony_ci return NULL; 407e1051a39Sopenharmony_ci return internal_delete(st, st->num - 1); 408e1051a39Sopenharmony_ci} 409e1051a39Sopenharmony_ci 410e1051a39Sopenharmony_civoid OPENSSL_sk_zero(OPENSSL_STACK *st) 411e1051a39Sopenharmony_ci{ 412e1051a39Sopenharmony_ci if (st == NULL || st->num == 0) 413e1051a39Sopenharmony_ci return; 414e1051a39Sopenharmony_ci memset(st->data, 0, sizeof(*st->data) * st->num); 415e1051a39Sopenharmony_ci st->num = 0; 416e1051a39Sopenharmony_ci} 417e1051a39Sopenharmony_ci 418e1051a39Sopenharmony_civoid OPENSSL_sk_pop_free(OPENSSL_STACK *st, OPENSSL_sk_freefunc func) 419e1051a39Sopenharmony_ci{ 420e1051a39Sopenharmony_ci int i; 421e1051a39Sopenharmony_ci 422e1051a39Sopenharmony_ci if (st == NULL) 423e1051a39Sopenharmony_ci return; 424e1051a39Sopenharmony_ci for (i = 0; i < st->num; i++) 425e1051a39Sopenharmony_ci if (st->data[i] != NULL) 426e1051a39Sopenharmony_ci func((char *)st->data[i]); 427e1051a39Sopenharmony_ci OPENSSL_sk_free(st); 428e1051a39Sopenharmony_ci} 429e1051a39Sopenharmony_ci 430e1051a39Sopenharmony_civoid OPENSSL_sk_free(OPENSSL_STACK *st) 431e1051a39Sopenharmony_ci{ 432e1051a39Sopenharmony_ci if (st == NULL) 433e1051a39Sopenharmony_ci return; 434e1051a39Sopenharmony_ci OPENSSL_free(st->data); 435e1051a39Sopenharmony_ci OPENSSL_free(st); 436e1051a39Sopenharmony_ci} 437e1051a39Sopenharmony_ci 438e1051a39Sopenharmony_ciint OPENSSL_sk_num(const OPENSSL_STACK *st) 439e1051a39Sopenharmony_ci{ 440e1051a39Sopenharmony_ci return st == NULL ? -1 : st->num; 441e1051a39Sopenharmony_ci} 442e1051a39Sopenharmony_ci 443e1051a39Sopenharmony_civoid *OPENSSL_sk_value(const OPENSSL_STACK *st, int i) 444e1051a39Sopenharmony_ci{ 445e1051a39Sopenharmony_ci if (st == NULL || i < 0 || i >= st->num) 446e1051a39Sopenharmony_ci return NULL; 447e1051a39Sopenharmony_ci return (void *)st->data[i]; 448e1051a39Sopenharmony_ci} 449e1051a39Sopenharmony_ci 450e1051a39Sopenharmony_civoid *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data) 451e1051a39Sopenharmony_ci{ 452e1051a39Sopenharmony_ci if (st == NULL) { 453e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); 454e1051a39Sopenharmony_ci return NULL; 455e1051a39Sopenharmony_ci } 456e1051a39Sopenharmony_ci if (i < 0 || i >= st->num) { 457e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT, 458e1051a39Sopenharmony_ci "i=%d", i); 459e1051a39Sopenharmony_ci return NULL; 460e1051a39Sopenharmony_ci } 461e1051a39Sopenharmony_ci st->data[i] = data; 462e1051a39Sopenharmony_ci st->sorted = 0; 463e1051a39Sopenharmony_ci return (void *)st->data[i]; 464e1051a39Sopenharmony_ci} 465e1051a39Sopenharmony_ci 466e1051a39Sopenharmony_civoid OPENSSL_sk_sort(OPENSSL_STACK *st) 467e1051a39Sopenharmony_ci{ 468e1051a39Sopenharmony_ci if (st != NULL && !st->sorted && st->comp != NULL) { 469e1051a39Sopenharmony_ci if (st->num > 1) 470e1051a39Sopenharmony_ci qsort(st->data, st->num, sizeof(void *), st->comp); 471e1051a39Sopenharmony_ci st->sorted = 1; /* empty or single-element stack is considered sorted */ 472e1051a39Sopenharmony_ci } 473e1051a39Sopenharmony_ci} 474e1051a39Sopenharmony_ci 475e1051a39Sopenharmony_ciint OPENSSL_sk_is_sorted(const OPENSSL_STACK *st) 476e1051a39Sopenharmony_ci{ 477e1051a39Sopenharmony_ci return st == NULL ? 1 : st->sorted; 478e1051a39Sopenharmony_ci} 479