DEFINE_STACK_OF(3ossl)
π DEFINE_STACK_OF π
okay bestie, welcome to the 3ossl manual page for DEFINE_STACK_OF, brought to you by OpenSSL, and it is long, so this is part 1 of 2 β hydrate, sit down, we're doing this π«Ά
β¨ NAME β¨
The whole squad of names this page covers, no cap:
- the macros:
DEFINE_STACK_OF,DEFINE_STACK_OF_CONST,DEFINE_SPECIAL_STACK_OF,DEFINE_SPECIAL_STACK_OF_CONST - the generated per-type crew:
sk_TYPE_num,sk_TYPE_value,sk_TYPE_new,sk_TYPE_new_null,sk_TYPE_reserve,sk_TYPE_free,sk_TYPE_zero,sk_TYPE_delete,sk_TYPE_delete_ptr,sk_TYPE_push,sk_TYPE_unshift,sk_TYPE_pop,sk_TYPE_shift,sk_TYPE_pop_free,sk_TYPE_insert,sk_TYPE_set,sk_TYPE_find,sk_TYPE_find_ex,sk_TYPE_find_all,sk_TYPE_sort,sk_TYPE_is_sorted,sk_TYPE_dup,sk_TYPE_deep_copy,sk_TYPE_set_cmp_func,sk_TYPE_new_reserve - and the underlying utility fam:
OPENSSL_sk_deep_copy,OPENSSL_sk_delete,OPENSSL_sk_delete_ptr,OPENSSL_sk_dup,OPENSSL_sk_find,OPENSSL_sk_find_ex,OPENSSL_sk_find_all,OPENSSL_sk_free,OPENSSL_sk_insert,OPENSSL_sk_is_sorted,OPENSSL_sk_new,OPENSSL_sk_new_null,OPENSSL_sk_new_reserve,OPENSSL_sk_num,OPENSSL_sk_pop,OPENSSL_sk_pop_free,OPENSSL_sk_push,OPENSSL_sk_reserve,OPENSSL_sk_set,OPENSSL_sk_set_cmp_func,OPENSSL_sk_shift,OPENSSL_sk_sort,OPENSSL_sk_unshift,OPENSSL_sk_value,OPENSSL_sk_zero
and what is all of this? a stack container π periodt.
πΈ SYNOPSIS πΈ
#include <openssl/safestack.h>
STACK_OF(TYPE)
DEFINE_STACK_OF(TYPE)
DEFINE_STACK_OF_CONST(TYPE)
DEFINE_SPECIAL_STACK_OF(FUNCTYPE, TYPE)
DEFINE_SPECIAL_STACK_OF_CONST(FUNCTYPE, TYPE)
typedef int (*sk_TYPE_compfunc)(const TYPE *const *a, const TYPE *const *b);
typedef TYPE * (*sk_TYPE_copyfunc)(const TYPE *a);
typedef void (*sk_TYPE_freefunc)(TYPE *a);
int sk_TYPE_num(const STACK_OF(TYPE) *sk);
TYPE *sk_TYPE_value(const STACK_OF(TYPE) *sk, int idx);
STACK_OF(TYPE) *sk_TYPE_new(sk_TYPE_compfunc compare);
STACK_OF(TYPE) *sk_TYPE_new_null(void);
int sk_TYPE_reserve(STACK_OF(TYPE) *sk, int n);
void sk_TYPE_free(STACK_OF(TYPE) *sk);
void sk_TYPE_zero(STACK_OF(TYPE) *sk);
TYPE *sk_TYPE_delete(STACK_OF(TYPE) *sk, int i);
TYPE *sk_TYPE_delete_ptr(STACK_OF(TYPE) *sk, TYPE *ptr);
int sk_TYPE_push(STACK_OF(TYPE) *sk, const TYPE *ptr);
int sk_TYPE_unshift(STACK_OF(TYPE) *sk, const TYPE *ptr);
TYPE *sk_TYPE_pop(STACK_OF(TYPE) *sk);
TYPE *sk_TYPE_shift(STACK_OF(TYPE) *sk);
void sk_TYPE_pop_free(STACK_OF(TYPE) *sk, sk_TYPE_freefunc freefunc);
int sk_TYPE_insert(STACK_OF(TYPE) *sk, TYPE *ptr, int idx);
TYPE *sk_TYPE_set(STACK_OF(TYPE) *sk, int idx, const TYPE *ptr);
int sk_TYPE_find(STACK_OF(TYPE) *sk, TYPE *ptr);
int sk_TYPE_find_ex(STACK_OF(TYPE) *sk, TYPE *ptr);
int sk_TYPE_find_all(STACK_OF(TYPE) *sk, TYPE *ptr, int *pnum);
void sk_TYPE_sort(const STACK_OF(TYPE) *sk);
int sk_TYPE_is_sorted(const STACK_OF(TYPE) *sk);
STACK_OF(TYPE) *sk_TYPE_dup(const STACK_OF(TYPE) *sk);
STACK_OF(TYPE) *sk_TYPE_deep_copy(const STACK_OF(TYPE) *sk,
sk_TYPE_copyfunc copyfunc,
sk_TYPE_freefunc freefunc);
sk_TYPE_compfunc (*sk_TYPE_set_cmp_func(STACK_OF(TYPE) *sk,
sk_TYPE_compfunc compare));
STACK_OF(TYPE) *sk_TYPE_new_reserve(sk_TYPE_compfunc compare, int n);
π¦ DESCRIPTION π¦
So here's the whole vibe: apps can build and use their own stacks, and all you gotta do is drop any of the macros described below into a header file. Those macros are the ones that cook up typesafe inline functions that wrap themselves around the utility OPENSSL_sk_ API. And every single time you see TYPE on this page? That's just a placeholder, bestie β swap in literally any of the OpenSSL datatypes, like X509, and you're golden β¨
The STACK_OF() macro returns the name for a stack of the specified TYPE. It's an opaque pointer to a structure declaration, and you can use it in every header file that references the stack. Then there are several DEFINE... macros that create static inline functions for all of the functions described on this page. Normally you'd use those in one source file, and the stack manipulation gets wrapped with application-specific functions. iykyk π
DEFINE_STACK_OF() creates a set of functions for a stack of TYPE elements. The type is referenced by STACK_OF(TYPE) and each function name begins with sk_TYPE_. And DEFINE_STACK_OF_CONST() is identical to DEFINE_STACK_OF() except each element is constant π
/* DEFINE_STACK_OF(TYPE) */
TYPE *sk_TYPE_value(STACK_OF(TYPE) *sk, int idx);
/* DEFINE_STACK_OF_CONST(TYPE) */
const TYPE *sk_TYPE_value(STACK_OF(TYPE) *sk, int idx);
DEFINE_SPECIAL_STACK_OF() and DEFINE_SPECIAL_STACK_OF_CONST() are similar, except FUNCNAME is used in the function names:
/* DEFINE_SPECIAL_STACK_OF(TYPE, FUNCNAME) */
TYPE *sk_FUNCNAME_value(STACK_OF(TYPE) *sk, int idx);
/* DEFINE_SPECIAL_STACK_OF(TYPE, FUNCNAME) */
const TYPE *sk_FUNCNAME_value(STACK_OF(TYPE) *sk, int idx);
π the function rundown, one by one π
sk_TYPE_num()β returns the number of elements insk, or-1ifskisNULL.sk_TYPE_value()β returns elementidxinsk, whereidxstarts at zero. Ifidxis out of range thenNULLis returned.sk_TYPE_new()β allocates a new empty stack using comparison functioncompare. IfcompareisNULLthen no comparison function is used. This function is equivalent tosk_TYPE_new_reserve(compare, 0).sk_TYPE_new_null()β allocates a new empty stack with no comparison function. This function is equivalent tosk_TYPE_new_reserve(NULL, 0).sk_TYPE_reserve()β allocates additional memory in theskstructure such that the nextncalls tosk_TYPE_insert(),sk_TYPE_push()orsk_TYPE_unshift()will not fail or cause memory to be allocated or reallocated. Ifnis zero, any excess space allocated in theskstructure is freed. On errorskis unchanged.sk_TYPE_new_reserve()β allocates a new stack. The new stack will have additional memory allocated to holdnelements ifnis positive. The nextncalls tosk_TYPE_insert(),sk_TYPE_push()orsk_TYPE_unshift()will not fail or cause memory to be allocated or reallocated. Ifnis zero or less than zero, no memory is allocated.sk_TYPE_new_reserve()also sets the comparison functioncompareto the newly created stack. IfcompareisNULLthen no comparison function is used.sk_TYPE_set_cmp_func()β sets the comparison function ofsktocompare. The previous comparison function is returned, orNULLif there was no previous comparison function.sk_TYPE_free()β frees up theskstructure. It does not free up any elements ofsk.
after this call sk is no longer valid, bestie. it's giving expired π do not touch it.
sk_TYPE_zero()β sets the number of elements inskto zero. It does not freesk, so after this callskis still valid π«Άsk_TYPE_pop_free()β frees up all elements ofskandskitself. The free functionfreefunc()is called on each element to free it.sk_TYPE_delete()β deletes elementifromsk. It returns the deleted element, orNULLifiis out of range.sk_TYPE_delete_ptr()β deletes element matchingptrfromsk. It returns the deleted element, orNULLif no element matchingptrwas found.sk_TYPE_insert()β insertsptrintoskat positionidx. Any existing elements at or afteridxare moved downwards. Ifidxis out of range the new element is appended tosk.sk_TYPE_insert()either returns the number of elements inskafter the new element is inserted, or zero if an error (such as memory allocation failure) occurred.sk_TYPE_push()β appendsptrtosk; it is equivalent to:
sk_TYPE_insert(sk, ptr, -1);
sk_TYPE_unshift()β insertsptrat the start ofsk; it is equivalent to:
sk_TYPE_insert(sk, ptr, 0);
sk_TYPE_pop()β returns and removes the last element fromsk.sk_TYPE_shift()β returns and removes the first element fromsk.sk_TYPE_set()β sets elementidxofsktoptr, replacing the current element. The new element value is returned, orNULLif an error occurred: this will only happen ifskisNULLoridxis out of range.sk_TYPE_find()β searchesskfor the elementptr. In the case where no comparison function has been specified, the function performs a linear search for a pointer equal toptr. In the case where a comparison function has been specified, the function performs a search for a element that the comparison function indicates is a match. If the stack is sorted, a binary search is used, otherwise, a linear search is used.sk_TYPE_find()returns the index of a matching element, or-1if there is no match.sk_TYPE_find_ex()β operates likesk_TYPE_find()except when a comparison function has been specified and no matching element is found. Instead of returning-1,sk_TYPE_find_ex()returns the index of the element either before or after the location whereptrwould be if it were present insk. The function also does not guarantee that the first matching element in the sorted stack is returned. (yes, it's the chaotic one, and that's the whole point π)sk_TYPE_find_all()β operates likesk_TYPE_find()but it also sets the*pnumto number of matching elements in the stack. In case no comparison function has been specified the*pnumwill be always set to1if matching element was found,0otherwise.sk_TYPE_sort()β sortsskusing the supplied comparison function.sk_TYPE_is_sorted()β returns1ifskis sorted and0otherwise.sk_TYPE_dup()β returns a shallow copy ofsk, or an empty stack if the passed stack isNULL. Note the pointers in the copy are identical to the original. (shallow = the vibes are shared, not cloned π¦)sk_TYPE_deep_copy()β returns a new stack where each element has been copied, or an empty stack if the passed stack isNULL. Copying is performed by the suppliedcopyfunc()and freeing byfreefunc().
heads up: the function freefunc() is only called if an error occurs. not on a happy path, not as cleanup β only on error. don't forget it π
NOTES π§ β¨
okay bestie, before you go wild with stacks, read this, because it's giving βimportant safety briefingβ energy.
- Threads? Be careful. Any operation that makes a stack bigger β like
sk_TYPE_insert()orsk_TYPE_push()β can βgrowβ the size of an internal array, and that can cause race conditions if the same stack is accessed in a different thread. Alsosk_TYPE_find()andsk_TYPE_sort()can reorder the stack, so yeah, same caution applies. multithreaded chaos is not the vibe π - Any comparison function you supply should use a metric suitable for a binary search operation. That means it should return zero, a positive value, or a negative value if
ais equal to, greater than, or less thanb, respectively. (Basically:0= same,+= a bigger,-= b bigger. Slay.) β¨ - Watch those find return values, fr fr.
sk_TYPE_find()andsk_TYPE_find_ex()return an index to the matching element. And here's the trap:0means a matching first element. A failed search is indicated by a-1return value. So don't treat0as βnothing foundβ β that's not it, bestie. π STACK_OF(),DEFINE_STACK_OF(),DEFINE_STACK_OF_CONST(), andDEFINE_SPECIAL_STACK_OF()are implemented as macros. iykyk π- It is not an error to call
sk_TYPE_num(),sk_TYPE_value(),sk_TYPE_free(),sk_TYPE_zero(),sk_TYPE_pop_free(),sk_TYPE_delete(),sk_TYPE_delete_ptr(),sk_TYPE_pop(),sk_TYPE_shift(),sk_TYPE_find(),sk_TYPE_find_ex(), andsk_TYPE_find_all()on aNULLstack, an empty stack, or with an invalid index. An error is not raised in these conditions. no drama, no error π«Ά - The underlying utility
OPENSSL_sk_API should not be used directly. It defines these functions:OPENSSL_sk_deep_copy(),OPENSSL_sk_delete(),OPENSSL_sk_delete_ptr(),OPENSSL_sk_dup(),OPENSSL_sk_find(),OPENSSL_sk_find_ex(),OPENSSL_sk_find_all(),OPENSSL_sk_free(),OPENSSL_sk_insert(),OPENSSL_sk_is_sorted(),OPENSSL_sk_new(),OPENSSL_sk_new_null(),OPENSSL_sk_new_reserve(),OPENSSL_sk_num(),OPENSSL_sk_pop(),OPENSSL_sk_pop_free(),OPENSSL_sk_push(),OPENSSL_sk_reserve(),OPENSSL_sk_set(),OPENSSL_sk_set_cmp_func(),OPENSSL_sk_shift(),OPENSSL_sk_sort(),OPENSSL_sk_unshift(),OPENSSL_sk_value(),OPENSSL_sk_zero().
RETURN VALUES ππ¦
Here's what every function hands back, bestie. No guessing.
sk_TYPE_num()returns the number of elements in the stack, or-1if the passed stack isNULL.sk_TYPE_value()returns a pointer to a stack element, orNULLif the index is out of range.sk_TYPE_new(),sk_TYPE_new_null(), andsk_TYPE_new_reserve()return an empty stack, orNULLif an error occurs.sk_TYPE_reserve()returns1on successful allocation of the required memory, or0on error.sk_TYPE_set_cmp_func()returns the old comparison function, orNULLif there was no old comparison function.sk_TYPE_free(),sk_TYPE_zero(),sk_TYPE_pop_free(), andsk_TYPE_sort()do not return values. (Iconic no-return energy. π)sk_TYPE_pop(),sk_TYPE_shift(),sk_TYPE_delete(), andsk_TYPE_delete_ptr()return a pointer to the deleted element, orNULLon error.sk_TYPE_insert(),sk_TYPE_push(), andsk_TYPE_unshift()return the total number of elements in the stack, and0if an error occurred.sk_TYPE_set()returns a pointer to the replacement element, orNULLon error.sk_TYPE_find()andsk_TYPE_find_ex()return an index to the found element, or-1on error.sk_TYPE_is_sorted()returns1if the stack is sorted and0if it is not.sk_TYPE_dup()andsk_TYPE_deep_copy()return a pointer to the copy of the stack, orNULLon error.
HISTORY π°οΈπ
- Before OpenSSL 1.1.0, this was implemented via macros and not inline functions, and was not a public API. ancient lore β¨
sk_TYPE_reserve()andsk_TYPE_new_reserve()were added in OpenSSL 1.1.1.- From OpenSSL 3.2.0, the
sk_TYPE_find(),sk_TYPE_find_ex(), andsk_TYPE_find_all()calls are read-only and do not sort the stack. To avoid any performance implications this change introduces,sk_TYPE_sort()should be called before these find operations. so sort first, bestie π₯ - Before OpenSSL 3.3.0,
sk_TYPE_push()returned-1ifskwasNULL. It was changed to return0in this condition as for other errors. glow-up moment π
COPYRIGHT ππ
Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the βLicenseβ). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.
And that's the whole vibe check, bestie. The footer on this one says it's version 3.5.9, dated 2026-09-29, and it's the DEFINE_STACK_OF(3ossl) page. Go forth and stack responsibly. πβ¨
π¦ where this page comes from
- fedora 43: openssl-devel 1:3.5.9-1.fc43 Β· Apache-2.0
- fedora 43: openssl-devel 1:3.5.9-1.fc43 Β· Apache-2.0
- fedora 44: openssl-devel 1:3.5.9-1.fc44 Β· Apache-2.0
- fedora 44: openssl-devel 1:3.5.9-1.fc44 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms