{
OPENSSL_sk_compfunc old = sk->comp;
- if (sk->comp != c)
+ if (sk->comp != c && sk->num > 1)
sk->sorted = 0;
sk->comp = c;
return old;
}
-OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk)
+static OPENSSL_STACK *internal_copy(const OPENSSL_STACK *sk,
+ OPENSSL_sk_copyfunc copy_func,
+ OPENSSL_sk_freefunc free_func)
{
OPENSSL_STACK *ret;
+ int i;
- if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
+ if ((ret = OPENSSL_sk_new_null()) == NULL)
goto err;
- if (sk == NULL) {
- ret->num = 0;
- ret->sorted = 0;
- ret->comp = NULL;
- } else {
- /* direct structure assignment */
- *ret = *sk;
- }
+ if (sk == NULL)
+ goto done;
- if (sk == NULL || sk->num == 0) {
- /* postpone |ret->data| allocation */
- ret->data = NULL;
- ret->num_alloc = 0;
- return ret;
- }
+ /* direct structure assignment */
+ *ret = *sk;
+ ret->data = NULL;
+ ret->num_alloc = 0;
+
+ if (ret->num == 0)
+ goto done; /* nothing to copy */
- /* duplicate |sk->data| content */
- ret->data = OPENSSL_malloc_array(sk->num_alloc, sizeof(*ret->data));
+ ret->num_alloc = ret->num > min_nodes ? ret->num : min_nodes;
+ ret->data = OPENSSL_calloc(ret->num_alloc, sizeof(*ret->data));
if (ret->data == NULL)
goto err;
- memcpy(ret->data, sk->data, sizeof(void *) * sk->num);
+ if (copy_func == NULL) {
+ memcpy(ret->data, sk->data, sizeof(*ret->data) * ret->num);
+ } else {
+ for (i = 0; i < ret->num; ++i) {
+ if (sk->data[i] == NULL)
+ continue;
+ if ((ret->data[i] = copy_func(sk->data[i])) == NULL) {
+ while (--i >= 0)
+ if (ret->data[i] != NULL)
+ free_func((void *)ret->data[i]);
+ goto err;
+ }
+ }
+ }
+
+ done:
return ret;
err:
OPENSSL_sk_copyfunc copy_func,
OPENSSL_sk_freefunc free_func)
{
- OPENSSL_STACK *ret;
- int i;
-
- if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
- goto err;
-
- if (sk == NULL) {
- ret->num = 0;
- ret->sorted = 0;
- ret->comp = NULL;
- } else {
- /* direct structure assignment */
- *ret = *sk;
- }
-
- if (sk == NULL || sk->num == 0) {
- /* postpone |ret| data allocation */
- ret->data = NULL;
- ret->num_alloc = 0;
- return ret;
- }
-
- ret->num_alloc = sk->num > min_nodes ? sk->num : min_nodes;
- ret->data = OPENSSL_calloc(ret->num_alloc, sizeof(*ret->data));
- if (ret->data == NULL)
- goto err;
-
- for (i = 0; i < ret->num; ++i) {
- if (sk->data[i] == NULL)
- continue;
- if ((ret->data[i] = copy_func(sk->data[i])) == NULL) {
- while (--i >= 0)
- if (ret->data[i] != NULL)
- free_func((void *)ret->data[i]);
- goto err;
- }
- }
- return ret;
+ return internal_copy(sk, copy_func, free_func);
+}
- err:
- OPENSSL_sk_free(ret);
- return NULL;
+OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk)
+{
+ return internal_copy(sk, NULL, NULL);
}
OPENSSL_STACK *OPENSSL_sk_new_null(void)
return NULL;
st->comp = c;
+ st->sorted = 1; /* empty or single-element stack is considered sorted */
if (n <= 0)
return st;
st->data[loc] = data;
}
st->num++;
- st->sorted = 0;
+ st->sorted = st->num <= 1;
return st->num;
}
memmove(&st->data[loc], &st->data[loc + 1],
sizeof(st->data[0]) * (st->num - loc - 1));
st->num--;
+ st->sorted = st->sorted || st->num <= 1;
return (void *)ret;
}
return NULL;
}
st->data[i] = data;
- st->sorted = 0;
+ st->sorted = st->num <= 1;
return (void *)st->data[i];
}
return 0;
}
+static int int_compare_backward(const int *const *a, const int *const *b)
+{
+ if (**a > **b)
+ return -1;
+ if (**a < **b)
+ return 1;
+ return 0;
+}
+
static int test_int_stack(int reserve)
{
static int v[] = { 1, 2, -4, 16, 999, 1, -173, 1, 9 };
/* Check push and num */
for (i = 0; i < n; i++) {
+ /* Empty or single element stack should be sorted */
+ if ((i == 0 || i == 1) && !TEST_true(sk_sint_is_sorted(s)))
+ goto end;
if (!TEST_int_eq(sk_sint_num(s), i)) {
TEST_info("int stack size %d", i);
goto end;
/* sorting */
if (!TEST_false(sk_sint_is_sorted(s)))
goto end;
+ (void)sk_sint_set_cmp_func(s, &int_compare_backward);
+ sk_sint_sort(s);
+ if (!TEST_true(sk_sint_is_sorted(s))) /* should be sorted */
+ goto end;
+ (void)sk_sint_set_cmp_func(s, &int_compare_backward);
+ if (!TEST_true(sk_sint_is_sorted(s))) /* should still be sorted */
+ goto end;
(void)sk_sint_set_cmp_func(s, &int_compare);
+ if (!TEST_false(sk_sint_is_sorted(s))) /* should no longer be sorted */
+ goto end;
sk_sint_sort(s);
- if (!TEST_true(sk_sint_is_sorted(s)))
+ if (!TEST_true(sk_sint_is_sorted(s))) /* now should be sorted again */
goto end;
/* find sorted -- the value is matched so we don't need to locate it */
{
static const unsigned char v[] = { 1, 3, 7, 5, 255, 0 };
const int n = OSSL_NELEM(v);
- STACK_OF(uchar) *s = sk_uchar_new(&uchar_compare), *r = NULL;
+ STACK_OF(uchar) *s = sk_uchar_new(&uchar_compare), *r = NULL, *q = NULL;
int i;
int testresult = 0;
r = sk_uchar_dup(s);
if (!TEST_int_eq(sk_uchar_num(r), n))
goto end;
+ q = sk_uchar_dup(s);
+ if (!TEST_int_eq(sk_uchar_num(q), n))
+ goto end;
sk_uchar_sort(r);
+ sk_uchar_sort(q);
/* pop */
- for (i = 0; i < n; i++)
+ for (i = 0; i < n; i++) {
if (!TEST_ptr_eq(sk_uchar_pop(s), v + i)) {
TEST_info("uchar pop %d", i);
goto end;
}
+ /* Previously unsorted stack of more than 1 element remains unsorted */
+ if (i < n - 2 && !TEST_false(sk_uchar_is_sorted(s)))
+ goto end;
+ /* A single or zero element stack should be sorted */
+ if (i > n - 2 && !TEST_true(sk_uchar_is_sorted(s)))
+ goto end;
+ }
/* free -- we rely on the debug malloc to detect leakage here */
sk_uchar_free(s);
s = NULL;
+ /* pop */
+ for (i = 0; i < n; i++) {
+ /* A sorted stack should remain sorted */
+ if (!TEST_true(sk_uchar_is_sorted(q)))
+ goto end;
+ }
+ /* free -- we rely on the debug malloc to detect leakage here */
+ sk_uchar_free(q);
+ q = NULL;
+
/* dup again */
if (!TEST_int_eq(sk_uchar_num(r), n))
goto end;