blob: 72da30d222a194e5c9de5f82fee8456ad4ca16bf [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.] */
56
57#ifndef OPENSSL_HEADER_STACK_H
58#define OPENSSL_HEADER_STACK_H
59
60#include <openssl/base.h>
61
Adam Langley95c29f32014-06-20 12:00:00 -070062#if defined(__cplusplus)
63extern "C" {
64#endif
65
66
David Benjamin4512b792017-08-18 19:21:50 -040067// A stack, in OpenSSL, is an array of pointers. They are the most commonly
68// used collection object.
69//
David Benjamin7f857ea2022-06-13 11:47:31 -040070// This file defines macros for type-safe use of the stack functions. A stack
71// type is named like |STACK_OF(FOO)| and is accessed with functions named
72// like |sk_FOO_*|. Note the stack will typically contain /pointers/ to |FOO|.
David Benjamin4512b792017-08-18 19:21:50 -040073//
David Benjamin7f857ea2022-06-13 11:47:31 -040074// The |DECLARE_STACK_OF| macro makes |STACK_OF(FOO)| available, and
75// |DEFINE_STACK_OF| makes the corresponding functions available.
Adam Langley95c29f32014-06-20 12:00:00 -070076
77
David Benjamin7f857ea2022-06-13 11:47:31 -040078// Defining stacks.
79
80// STACK_OF expands to the stack type for |type|.
81#define STACK_OF(type) struct stack_st_##type
82
83// DECLARE_STACK_OF declares the |STACK_OF(type)| type. It does not make the
84// corresponding |sk_type_*| functions available. This macro should be used in
85// files which only need the type.
86#define DECLARE_STACK_OF(type) STACK_OF(type);
87
88// DEFINE_NAMED_STACK_OF defines |STACK_OF(name)| to be a stack whose elements
89// are |type| *. This macro makes the |sk_name_*| functions available.
90//
91// It is not necessary to use |DECLARE_STACK_OF| in files which use this macro.
92#define DEFINE_NAMED_STACK_OF(name, type) \
93 BORINGSSL_DEFINE_STACK_OF_IMPL(name, type *, const type *) \
94 BORINGSSL_DEFINE_STACK_TRAITS(name, type, false)
95
96// DEFINE_STACK_OF defines |STACK_OF(type)| to be a stack whose elements are
97// |type| *. This macro makes the |sk_type_*| functions available.
98//
99// It is not necessary to use |DECLARE_STACK_OF| in files which use this macro.
100#define DEFINE_STACK_OF(type) DEFINE_NAMED_STACK_OF(type, type)
101
102// DEFINE_CONST_STACK_OF defines |STACK_OF(type)| to be a stack whose elements
103// are const |type| *. This macro makes the |sk_type_*| functions available.
104//
105// It is not necessary to use |DECLARE_STACK_OF| in files which use this macro.
106#define DEFINE_CONST_STACK_OF(type) \
107 BORINGSSL_DEFINE_STACK_OF_IMPL(type, const type *, const type *) \
108 BORINGSSL_DEFINE_STACK_TRAITS(type, const type, true)
109
110
111// Using stacks.
112//
113// After the |DEFINE_STACK_OF| macro is used, the following functions are
114// available.
115
116#if 0 // Sample
117
118// sk_SAMPLE_free_func is a callback to free an element in a stack.
119typedef void (*sk_SAMPLE_free_func)(SAMPLE *);
120
121// sk_SAMPLE_copy_func is a callback to copy an element in a stack. It should
122// return the copy or NULL on error.
David Benjamindf8a55b2023-01-04 15:52:36 -0800123typedef SAMPLE *(*sk_SAMPLE_copy_func)(const SAMPLE *);
David Benjamin7f857ea2022-06-13 11:47:31 -0400124
125// sk_SAMPLE_cmp_func is a callback to compare |*a| to |*b|. It should return a
126// value < 0, 0, or > 0 if |*a| is less than, equal to, or greater than |*b|,
127// respectively. Note the extra indirection - the function is given a pointer
128// to a pointer to the element. This is the |qsort|/|bsearch| comparison
129// function applied to an array of |SAMPLE*|.
130//
131// TODO(https://crbug.com/boringssl/498): The parameters should be
132// |const SAMPLE *const *|.
133typedef int (*sk_SAMPLE_cmp_func)(const SAMPLE **a, const SAMPLE **b);
134
135// sk_SAMPLE_new creates a new, empty stack with the given comparison function,
136// which may be NULL. It returns the new stack or NULL on allocation failure.
137STACK_OF(SAMPLE) *sk_SAMPLE_new(sk_SAMPLE_cmp_func comp);
138
139// sk_SAMPLE_new_null creates a new, empty stack. It returns the new stack or
140// NULL on allocation failure.
141STACK_OF(SAMPLE) *sk_SAMPLE_new_null(void);
142
143// sk_SAMPLE_num returns the number of elements in |sk|.
144size_t sk_SAMPLE_num(const STACK_OF(SAMPLE) *sk);
145
146// sk_SAMPLE_zero resets |sk| to the empty state but does nothing to free the
147// individual elements themselves.
148void sk_SAMPLE_zero(STACK_OF(SAMPLE) *sk);
149
150// sk_SAMPLE_value returns the |i|th pointer in |sk|, or NULL if |i| is out of
151// range.
152SAMPLE *sk_SAMPLE_value(const STACK_OF(SAMPLE) *sk, size_t i);
153
154// sk_SAMPLE_set sets the |i|th pointer in |sk| to |p| and returns |p|. If |i|
155// is out of range, it returns NULL.
156SAMPLE *sk_SAMPLE_set(STACK_OF(SAMPLE) *sk, size_t i, SAMPLE *p);
157
158// sk_SAMPLE_free frees |sk|, but does nothing to free the individual elements.
159// Use |sk_SAMPLE_pop_free| to also free the elements.
160void sk_SAMPLE_free(STACK_OF(SAMPLE) *sk);
161
162// sk_SAMPLE_pop_free calls |free_func| on each element in |sk| and then
163// frees the stack itself.
164void sk_SAMPLE_pop_free(STACK_OF(SAMPLE) *sk, sk_SAMPLE_free_func free_func);
165
166// sk_SAMPLE_insert inserts |p| into the stack at index |where|, moving existing
167// elements if needed. It returns the length of the new stack, or zero on
168// error.
169size_t sk_SAMPLE_insert(STACK_OF(SAMPLE) *sk, SAMPLE *p, size_t where);
170
171// sk_SAMPLE_delete removes the pointer at index |where|, moving other elements
172// down if needed. It returns the removed pointer, or NULL if |where| is out of
173// range.
174SAMPLE *sk_SAMPLE_delete(STACK_OF(SAMPLE) *sk, size_t where);
175
176// sk_SAMPLE_delete_ptr removes, at most, one instance of |p| from |sk| based on
177// pointer equality. If an instance of |p| is found then |p| is returned,
178// otherwise it returns NULL.
179SAMPLE *sk_SAMPLE_delete_ptr(STACK_OF(SAMPLE) *sk, const SAMPLE *p);
180
David Benjamin49e07912022-12-26 10:41:26 -0500181// sk_SAMPLE_delete_if_func is the callback function for |sk_SAMPLE_delete_if|.
182// It should return one to remove |p| and zero to keep it.
183typedef int (*sk_SAMPLE_delete_if_func)(SAMPLE *p, void *data);
184
185// sk_SAMPLE_delete_if calls |func| with each element of |sk| and removes the
186// entries where |func| returned one. This function does not free or return
187// removed pointers so, if |sk| owns its contents, |func| should release the
188// pointers prior to returning one.
189void sk_SAMPLE_delete_if(STACK_OF(SAMPLE) *sk, sk_SAMPLE_delete_if_func func,
190 void *data);
191
David Benjamin7f857ea2022-06-13 11:47:31 -0400192// sk_SAMPLE_find find the first value in |sk| equal to |p|. |sk|'s comparison
193// function determines equality, or pointer equality if |sk| has no comparison
194// function.
195//
196// If the stack is sorted (see |sk_SAMPLE_sort|), this function uses a binary
197// search. Otherwise it performs a linear search. If it finds a matching
198// element, it writes the index to |*out_index| (if |out_index| is not NULL) and
199// returns one. Otherwise, it returns zero.
200//
201// Note this differs from OpenSSL. The type signature is slightly different, and
202// OpenSSL's version will implicitly sort |sk| if it has a comparison function
203// defined.
204int sk_SAMPLE_find(const STACK_OF(SAMPLE) *sk, size_t *out_index,
205 const SAMPLE *p);
206
207// sk_SAMPLE_shift removes and returns the first element in |sk|, or NULL if
208// |sk| is empty.
209SAMPLE *sk_SAMPLE_shift(STACK_OF(SAMPLE) *sk);
210
211// sk_SAMPLE_push appends |p| to |sk| and returns the length of the new stack,
212// or 0 on allocation failure.
213size_t sk_SAMPLE_push(STACK_OF(SAMPLE) *sk, SAMPLE *p);
214
215// sk_SAMPLE_pop removes and returns the last element of |sk|, or NULL if |sk|
216// is empty.
217SAMPLE *sk_SAMPLE_pop(STACK_OF(SAMPLE) *sk);
218
219// sk_SAMPLE_dup performs a shallow copy of a stack and returns the new stack,
220// or NULL on error. Use |sk_SAMPLE_deep_copy| to also copy the elements.
221STACK_OF(SAMPLE) *sk_SAMPLE_dup(const STACK_OF(SAMPLE) *sk);
222
223// sk_SAMPLE_sort sorts the elements of |sk| into ascending order based on the
224// comparison function. The stack maintains a "sorted" flag and sorting an
225// already sorted stack is a no-op.
226void sk_SAMPLE_sort(STACK_OF(SAMPLE) *sk);
227
228// sk_SAMPLE_is_sorted returns one if |sk| is known to be sorted and zero
229// otherwise.
230int sk_SAMPLE_is_sorted(const STACK_OF(SAMPLE) *sk);
231
232// sk_SAMPLE_set_cmp_func sets the comparison function to be used by |sk| and
233// returns the previous one.
234sk_SAMPLE_cmp_func sk_SAMPLE_set_cmp_func(STACK_OF(SAMPLE) *sk,
235 sk_SAMPLE_cmp_func comp);
236
237// sk_SAMPLE_deep_copy performs a copy of |sk| and of each of the non-NULL
238// elements in |sk| by using |copy_func|. If an error occurs, it calls
239// |free_func| to free any copies already made and returns NULL.
240STACK_OF(SAMPLE) *sk_SAMPLE_deep_copy(const STACK_OF(SAMPLE) *sk,
241 sk_SAMPLE_copy_func copy_func,
242 sk_SAMPLE_free_func free_func);
243
244#endif // Sample
245
246
247// Private functions.
248//
249// TODO(https://crbug.com/boringssl/499): Rename to |OPENSSL_sk_foo|, after
250// external code that calls them is fixed.
251
252// OPENSSL_sk_free_func is a function that frees an element in a stack. Note its
David Benjaminfb4e2e02018-09-23 15:59:51 -0500253// actual type is void (*)(T *) for some T. Low-level |sk_*| functions will be
254// passed a type-specific wrapper to call it correctly.
David Benjamin7f857ea2022-06-13 11:47:31 -0400255typedef void (*OPENSSL_sk_free_func)(void *ptr);
David Benjaminfb4e2e02018-09-23 15:59:51 -0500256
David Benjamin7f857ea2022-06-13 11:47:31 -0400257// OPENSSL_sk_copy_func is a function that copies an element in a stack. Note
David Benjamindf8a55b2023-01-04 15:52:36 -0800258// its actual type is T *(*)(const T *) for some T. Low-level |sk_*| functions
259// will be passed a type-specific wrapper to call it correctly.
260typedef void *(*OPENSSL_sk_copy_func)(const void *ptr);
David Benjaminfb4e2e02018-09-23 15:59:51 -0500261
David Benjamin7f857ea2022-06-13 11:47:31 -0400262// OPENSSL_sk_cmp_func is a comparison function that returns a value < 0, 0 or >
263// 0 if |*a| is less than, equal to or greater than |*b|, respectively. Note
264// the extra indirection - the function is given a pointer to a pointer to the
David Benjamin4512b792017-08-18 19:21:50 -0400265// element. This differs from the usual qsort/bsearch comparison function.
David Benjamin52483992018-09-23 16:31:03 -0500266//
David Benjamin167f1762022-06-12 13:47:08 -0400267// Note its actual type is |int (*)(const T **a, const T **b)|. Low-level |sk_*|
David Benjamin52483992018-09-23 16:31:03 -0500268// functions will be passed a type-specific wrapper to call it correctly.
David Benjamin167f1762022-06-12 13:47:08 -0400269//
David Benjaminff23b7c2022-12-27 00:21:35 -0500270// TODO(https://crbug.com/boringssl/498): This type should be
271// |const T *const *|. It is already fixed in OpenSSL 1.1.1, so hopefully we can
272// fix this compatibly.
David Benjamin7f857ea2022-06-13 11:47:31 -0400273typedef int (*OPENSSL_sk_cmp_func)(const void **a, const void **b);
Adam Langley95c29f32014-06-20 12:00:00 -0700274
David Benjamin49e07912022-12-26 10:41:26 -0500275// OPENSSL_sk_delete_if_func is the generic version of
276// |sk_SAMPLE_delete_if_func|.
277typedef int (*OPENSSL_sk_delete_if_func)(void *obj, void *data);
278
David Benjamin167f1762022-06-12 13:47:08 -0400279// The following function types call the above type-erased signatures with the
280// true types.
David Benjamin7f857ea2022-06-13 11:47:31 -0400281typedef void (*OPENSSL_sk_call_free_func)(OPENSSL_sk_free_func, void *);
David Benjamindf8a55b2023-01-04 15:52:36 -0800282typedef void *(*OPENSSL_sk_call_copy_func)(OPENSSL_sk_copy_func, const void *);
David Benjamin7f857ea2022-06-13 11:47:31 -0400283typedef int (*OPENSSL_sk_call_cmp_func)(OPENSSL_sk_cmp_func,
284 const void *const *,
285 const void *const *);
David Benjamin49e07912022-12-26 10:41:26 -0500286typedef int (*OPENSSL_sk_call_delete_if_func)(OPENSSL_sk_delete_if_func, void *,
287 void *);
David Benjamin167f1762022-06-12 13:47:08 -0400288
David Benjamin4512b792017-08-18 19:21:50 -0400289// stack_st contains an array of pointers. It is not designed to be used
290// directly, rather the wrapper macros should be used.
Adam Langley95c29f32014-06-20 12:00:00 -0700291typedef struct stack_st {
David Benjamin4512b792017-08-18 19:21:50 -0400292 // num contains the number of valid pointers in |data|.
Adam Langley95c29f32014-06-20 12:00:00 -0700293 size_t num;
294 void **data;
David Benjamin4512b792017-08-18 19:21:50 -0400295 // sorted is non-zero if the values pointed to by |data| are in ascending
296 // order, based on |comp|.
David Benjamin22edd872016-08-04 21:38:40 +0000297 int sorted;
David Benjamin4512b792017-08-18 19:21:50 -0400298 // num_alloc contains the number of pointers allocated in the buffer pointed
299 // to by |data|, which may be larger than |num|.
Adam Langley95c29f32014-06-20 12:00:00 -0700300 size_t num_alloc;
David Benjamin4512b792017-08-18 19:21:50 -0400301 // comp is an optional comparison function.
David Benjamin7f857ea2022-06-13 11:47:31 -0400302 OPENSSL_sk_cmp_func comp;
Adam Langley95c29f32014-06-20 12:00:00 -0700303} _STACK;
304
David Benjamin7f857ea2022-06-13 11:47:31 -0400305// The following are raw stack functions. They implement the corresponding typed
306// |sk_SAMPLE_*| functions generated by |DEFINE_STACK_OF|. Callers shouldn't be
307// using them. Rather, callers should use the typed functions.
308OPENSSL_EXPORT _STACK *sk_new(OPENSSL_sk_cmp_func comp);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700309OPENSSL_EXPORT _STACK *sk_new_null(void);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700310OPENSSL_EXPORT size_t sk_num(const _STACK *sk);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700311OPENSSL_EXPORT void sk_zero(_STACK *sk);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700312OPENSSL_EXPORT void *sk_value(const _STACK *sk, size_t i);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700313OPENSSL_EXPORT void *sk_set(_STACK *sk, size_t i, void *p);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700314OPENSSL_EXPORT void sk_free(_STACK *sk);
David Benjaminfb4e2e02018-09-23 15:59:51 -0500315OPENSSL_EXPORT void sk_pop_free_ex(_STACK *sk,
David Benjamin7f857ea2022-06-13 11:47:31 -0400316 OPENSSL_sk_call_free_func call_free_func,
317 OPENSSL_sk_free_func free_func);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700318OPENSSL_EXPORT size_t sk_insert(_STACK *sk, void *p, size_t where);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700319OPENSSL_EXPORT void *sk_delete(_STACK *sk, size_t where);
David Benjamin8d2f4b92018-09-23 15:11:41 -0500320OPENSSL_EXPORT void *sk_delete_ptr(_STACK *sk, const void *p);
David Benjamin49e07912022-12-26 10:41:26 -0500321OPENSSL_EXPORT void sk_delete_if(_STACK *sk,
322 OPENSSL_sk_call_delete_if_func call_func,
323 OPENSSL_sk_delete_if_func func, void *data);
David Benjamin52483992018-09-23 16:31:03 -0500324OPENSSL_EXPORT int sk_find(const _STACK *sk, size_t *out_index, const void *p,
David Benjamin7f857ea2022-06-13 11:47:31 -0400325 OPENSSL_sk_call_cmp_func call_cmp_func);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700326OPENSSL_EXPORT void *sk_shift(_STACK *sk);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700327OPENSSL_EXPORT size_t sk_push(_STACK *sk, void *p);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700328OPENSSL_EXPORT void *sk_pop(_STACK *sk);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700329OPENSSL_EXPORT _STACK *sk_dup(const _STACK *sk);
David Benjamin7f857ea2022-06-13 11:47:31 -0400330OPENSSL_EXPORT void sk_sort(_STACK *sk, OPENSSL_sk_call_cmp_func call_cmp_func);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700331OPENSSL_EXPORT int sk_is_sorted(const _STACK *sk);
David Benjamin7f857ea2022-06-13 11:47:31 -0400332OPENSSL_EXPORT OPENSSL_sk_cmp_func sk_set_cmp_func(_STACK *sk,
333 OPENSSL_sk_cmp_func comp);
David Benjamin167f1762022-06-12 13:47:08 -0400334OPENSSL_EXPORT _STACK *sk_deep_copy(const _STACK *sk,
David Benjamin7f857ea2022-06-13 11:47:31 -0400335 OPENSSL_sk_call_copy_func call_copy_func,
336 OPENSSL_sk_copy_func copy_func,
337 OPENSSL_sk_call_free_func call_free_func,
338 OPENSSL_sk_free_func free_func);
David Benjaminfb4e2e02018-09-23 15:59:51 -0500339
340// sk_pop_free behaves like |sk_pop_free_ex| but performs an invalid function
341// pointer cast. It exists because some existing callers called |sk_pop_free|
342// directly.
343//
344// TODO(davidben): Migrate callers to bssl::UniquePtr and remove this.
David Benjamin7f857ea2022-06-13 11:47:31 -0400345OPENSSL_EXPORT void sk_pop_free(_STACK *sk, OPENSSL_sk_free_func free_func);
David Benjamin01f8a8c2017-04-15 18:12:55 -0400346
David Benjamin01219532017-07-25 22:33:06 -0400347#if !defined(BORINGSSL_NO_CXX)
348extern "C++" {
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700349BSSL_NAMESPACE_BEGIN
David Benjamin01219532017-07-25 22:33:06 -0400350namespace internal {
351template <typename T>
352struct StackTraits {};
353}
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700354BSSL_NAMESPACE_END
David Benjamin01219532017-07-25 22:33:06 -0400355}
356
David Benjaminec783832017-07-25 23:23:03 -0400357#define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) \
358 extern "C++" { \
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700359 BSSL_NAMESPACE_BEGIN \
David Benjaminec783832017-07-25 23:23:03 -0400360 namespace internal { \
361 template <> \
362 struct StackTraits<STACK_OF(name)> { \
363 static constexpr bool kIsStack = true; \
364 using Type = type; \
365 static constexpr bool kIsConst = is_const; \
366 }; \
367 } \
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700368 BSSL_NAMESPACE_END \
David Benjamin01219532017-07-25 22:33:06 -0400369 }
370
371#else
David Benjaminec783832017-07-25 23:23:03 -0400372#define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const)
David Benjamin01219532017-07-25 22:33:06 -0400373#endif
374
David Benjamin7f857ea2022-06-13 11:47:31 -0400375#define BORINGSSL_DEFINE_STACK_OF_IMPL(name, ptrtype, constptrtype) \
376 /* We disable MSVC C4191 in this macro, which warns when pointers are cast \
377 * to the wrong type. While the cast itself is valid, it is often a bug \
378 * because calling it through the cast is UB. However, we never actually \
379 * call functions as |OPENSSL_sk_cmp_func|. The type is just a type-erased \
380 * function pointer. (C does not guarantee function pointers fit in \
381 * |void*|, and GCC will warn on this.) Thus we just disable the false \
382 * positive warning. */ \
383 OPENSSL_MSVC_PRAGMA(warning(push)) \
384 OPENSSL_MSVC_PRAGMA(warning(disable : 4191)) \
385 \
386 DECLARE_STACK_OF(name) \
387 \
388 typedef void (*sk_##name##_free_func)(ptrtype); \
David Benjamindf8a55b2023-01-04 15:52:36 -0800389 typedef ptrtype (*sk_##name##_copy_func)(constptrtype); \
David Benjamin49e07912022-12-26 10:41:26 -0500390 typedef int (*sk_##name##_cmp_func)(constptrtype *, constptrtype *); \
391 typedef int (*sk_##name##_delete_if_func)(ptrtype, void *); \
David Benjamin7f857ea2022-06-13 11:47:31 -0400392 \
393 OPENSSL_INLINE void sk_##name##_call_free_func( \
394 OPENSSL_sk_free_func free_func, void *ptr) { \
395 ((sk_##name##_free_func)free_func)((ptrtype)ptr); \
396 } \
397 \
398 OPENSSL_INLINE void *sk_##name##_call_copy_func( \
David Benjamindf8a55b2023-01-04 15:52:36 -0800399 OPENSSL_sk_copy_func copy_func, const void *ptr) { \
400 return (void *)((sk_##name##_copy_func)copy_func)((constptrtype)ptr); \
David Benjamin7f857ea2022-06-13 11:47:31 -0400401 } \
402 \
403 OPENSSL_INLINE int sk_##name##_call_cmp_func(OPENSSL_sk_cmp_func cmp_func, \
404 const void *const *a, \
405 const void *const *b) { \
406 /* The data is actually stored as |void*| pointers, so read the pointer \
407 * as |void*| and then pass the corrected type into the caller-supplied \
408 * function, which expects |constptrtype*|. */ \
409 constptrtype a_ptr = (constptrtype)*a; \
410 constptrtype b_ptr = (constptrtype)*b; \
411 return ((sk_##name##_cmp_func)cmp_func)(&a_ptr, &b_ptr); \
412 } \
413 \
David Benjamin49e07912022-12-26 10:41:26 -0500414 OPENSSL_INLINE int sk_##name##_call_delete_if_func( \
415 OPENSSL_sk_delete_if_func func, void *obj, void *data) { \
416 return ((sk_##name##_delete_if_func)func)((ptrtype)obj, data); \
417 } \
418 \
David Benjamin7f857ea2022-06-13 11:47:31 -0400419 OPENSSL_INLINE STACK_OF(name) *sk_##name##_new(sk_##name##_cmp_func comp) { \
420 return (STACK_OF(name) *)sk_new((OPENSSL_sk_cmp_func)comp); \
421 } \
422 \
423 OPENSSL_INLINE STACK_OF(name) *sk_##name##_new_null(void) { \
424 return (STACK_OF(name) *)sk_new_null(); \
425 } \
426 \
427 OPENSSL_INLINE size_t sk_##name##_num(const STACK_OF(name) *sk) { \
428 return sk_num((const _STACK *)sk); \
429 } \
430 \
431 OPENSSL_INLINE void sk_##name##_zero(STACK_OF(name) *sk) { \
432 sk_zero((_STACK *)sk); \
433 } \
434 \
435 OPENSSL_INLINE ptrtype sk_##name##_value(const STACK_OF(name) *sk, \
436 size_t i) { \
437 return (ptrtype)sk_value((const _STACK *)sk, i); \
438 } \
439 \
440 OPENSSL_INLINE ptrtype sk_##name##_set(STACK_OF(name) *sk, size_t i, \
441 ptrtype p) { \
442 return (ptrtype)sk_set((_STACK *)sk, i, (void *)p); \
443 } \
444 \
445 OPENSSL_INLINE void sk_##name##_free(STACK_OF(name) *sk) { \
446 sk_free((_STACK *)sk); \
447 } \
448 \
449 OPENSSL_INLINE void sk_##name##_pop_free(STACK_OF(name) *sk, \
450 sk_##name##_free_func free_func) { \
451 sk_pop_free_ex((_STACK *)sk, sk_##name##_call_free_func, \
452 (OPENSSL_sk_free_func)free_func); \
453 } \
454 \
455 OPENSSL_INLINE size_t sk_##name##_insert(STACK_OF(name) *sk, ptrtype p, \
456 size_t where) { \
457 return sk_insert((_STACK *)sk, (void *)p, where); \
458 } \
459 \
460 OPENSSL_INLINE ptrtype sk_##name##_delete(STACK_OF(name) *sk, \
461 size_t where) { \
462 return (ptrtype)sk_delete((_STACK *)sk, where); \
463 } \
464 \
465 OPENSSL_INLINE ptrtype sk_##name##_delete_ptr(STACK_OF(name) *sk, \
466 constptrtype p) { \
467 return (ptrtype)sk_delete_ptr((_STACK *)sk, (const void *)p); \
468 } \
469 \
David Benjamin49e07912022-12-26 10:41:26 -0500470 OPENSSL_INLINE void sk_##name##_delete_if( \
471 STACK_OF(name) *sk, sk_##name##_delete_if_func func, void *data) { \
472 sk_delete_if((_STACK *)sk, sk_##name##_call_delete_if_func, \
473 (OPENSSL_sk_delete_if_func)func, data); \
474 } \
475 \
David Benjamin7f857ea2022-06-13 11:47:31 -0400476 OPENSSL_INLINE int sk_##name##_find(const STACK_OF(name) *sk, \
477 size_t *out_index, constptrtype p) { \
478 return sk_find((const _STACK *)sk, out_index, (const void *)p, \
479 sk_##name##_call_cmp_func); \
480 } \
481 \
482 OPENSSL_INLINE ptrtype sk_##name##_shift(STACK_OF(name) *sk) { \
483 return (ptrtype)sk_shift((_STACK *)sk); \
484 } \
485 \
486 OPENSSL_INLINE size_t sk_##name##_push(STACK_OF(name) *sk, ptrtype p) { \
487 return sk_push((_STACK *)sk, (void *)p); \
488 } \
489 \
490 OPENSSL_INLINE ptrtype sk_##name##_pop(STACK_OF(name) *sk) { \
491 return (ptrtype)sk_pop((_STACK *)sk); \
492 } \
493 \
494 OPENSSL_INLINE STACK_OF(name) *sk_##name##_dup(const STACK_OF(name) *sk) { \
495 return (STACK_OF(name) *)sk_dup((const _STACK *)sk); \
496 } \
497 \
498 OPENSSL_INLINE void sk_##name##_sort(STACK_OF(name) *sk) { \
499 sk_sort((_STACK *)sk, sk_##name##_call_cmp_func); \
500 } \
501 \
502 OPENSSL_INLINE int sk_##name##_is_sorted(const STACK_OF(name) *sk) { \
503 return sk_is_sorted((const _STACK *)sk); \
504 } \
505 \
506 OPENSSL_INLINE sk_##name##_cmp_func sk_##name##_set_cmp_func( \
507 STACK_OF(name) *sk, sk_##name##_cmp_func comp) { \
508 return (sk_##name##_cmp_func)sk_set_cmp_func((_STACK *)sk, \
509 (OPENSSL_sk_cmp_func)comp); \
510 } \
511 \
512 OPENSSL_INLINE STACK_OF(name) *sk_##name##_deep_copy( \
513 const STACK_OF(name) *sk, sk_##name##_copy_func copy_func, \
514 sk_##name##_free_func free_func) { \
515 return (STACK_OF(name) *)sk_deep_copy( \
516 (const _STACK *)sk, sk_##name##_call_copy_func, \
517 (OPENSSL_sk_copy_func)copy_func, sk_##name##_call_free_func, \
518 (OPENSSL_sk_free_func)free_func); \
519 } \
520 \
David Benjamin167f1762022-06-12 13:47:08 -0400521 OPENSSL_MSVC_PRAGMA(warning(pop))
David Benjamin01f8a8c2017-04-15 18:12:55 -0400522
David Benjamin35b4a122018-07-14 17:04:41 -0400523
David Benjamin7f857ea2022-06-13 11:47:31 -0400524// Built-in stacks.
David Benjamin01f8a8c2017-04-15 18:12:55 -0400525
David Benjamin01f8a8c2017-04-15 18:12:55 -0400526typedef char *OPENSSL_STRING;
527
528DEFINE_STACK_OF(void)
David Benjamin1500ad02022-06-13 12:33:07 -0400529DEFINE_NAMED_STACK_OF(OPENSSL_STRING, char)
David Benjamin01f8a8c2017-04-15 18:12:55 -0400530
531
Adam Langley95c29f32014-06-20 12:00:00 -0700532#if defined(__cplusplus)
David Benjamin4512b792017-08-18 19:21:50 -0400533} // extern C
Adam Langley95c29f32014-06-20 12:00:00 -0700534#endif
535
David Benjamin01219532017-07-25 22:33:06 -0400536#if !defined(BORINGSSL_NO_CXX)
537extern "C++" {
538
539#include <type_traits>
540
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700541BSSL_NAMESPACE_BEGIN
David Benjamin01219532017-07-25 22:33:06 -0400542
543namespace internal {
544
545// Stacks defined with |DEFINE_CONST_STACK_OF| are freed with |sk_free|.
546template <typename Stack>
David Benjamin493d5cb2022-04-18 17:20:27 -0400547struct DeleterImpl<Stack, std::enable_if_t<StackTraits<Stack>::kIsConst>> {
David Benjamin01219532017-07-25 22:33:06 -0400548 static void Free(Stack *sk) { sk_free(reinterpret_cast<_STACK *>(sk)); }
549};
550
551// Stacks defined with |DEFINE_STACK_OF| are freed with |sk_pop_free| and the
552// corresponding type's deleter.
553template <typename Stack>
David Benjamin493d5cb2022-04-18 17:20:27 -0400554struct DeleterImpl<Stack, std::enable_if_t<!StackTraits<Stack>::kIsConst>> {
David Benjamin01219532017-07-25 22:33:06 -0400555 static void Free(Stack *sk) {
David Benjaminfb4e2e02018-09-23 15:59:51 -0500556 // sk_FOO_pop_free is defined by macros and bound by name, so we cannot
557 // access it from C++ here.
558 using Type = typename StackTraits<Stack>::Type;
559 sk_pop_free_ex(reinterpret_cast<_STACK *>(sk),
David Benjamin7f857ea2022-06-13 11:47:31 -0400560 [](OPENSSL_sk_free_func /* unused */, void *ptr) {
David Benjaminfb4e2e02018-09-23 15:59:51 -0500561 DeleterImpl<Type>::Free(reinterpret_cast<Type *>(ptr));
562 },
563 nullptr);
David Benjamin01219532017-07-25 22:33:06 -0400564 }
565};
566
David Benjaminec783832017-07-25 23:23:03 -0400567template <typename Stack>
568class StackIteratorImpl {
569 public:
570 using Type = typename StackTraits<Stack>::Type;
571 // Iterators must be default-constructable.
572 StackIteratorImpl() : sk_(nullptr), idx_(0) {}
573 StackIteratorImpl(const Stack *sk, size_t idx) : sk_(sk), idx_(idx) {}
574
575 bool operator==(StackIteratorImpl other) const {
576 return sk_ == other.sk_ && idx_ == other.idx_;
577 }
578 bool operator!=(StackIteratorImpl other) const {
579 return !(*this == other);
580 }
581
582 Type *operator*() const {
583 return reinterpret_cast<Type *>(
584 sk_value(reinterpret_cast<const _STACK *>(sk_), idx_));
585 }
586
587 StackIteratorImpl &operator++(/* prefix */) {
588 idx_++;
589 return *this;
590 }
591
592 StackIteratorImpl operator++(int /* postfix */) {
593 StackIteratorImpl copy(*this);
594 ++(*this);
595 return copy;
596 }
597
598 private:
599 const Stack *sk_;
600 size_t idx_;
601};
602
603template <typename Stack>
David Benjamin493d5cb2022-04-18 17:20:27 -0400604using StackIterator =
605 std::enable_if_t<StackTraits<Stack>::kIsStack, StackIteratorImpl<Stack>>;
David Benjaminec783832017-07-25 23:23:03 -0400606
David Benjamin01219532017-07-25 22:33:06 -0400607} // namespace internal
608
David Benjamin6e9321f2017-07-25 23:49:58 -0400609// PushToStack pushes |elem| to |sk|. It returns true on success and false on
610// allocation failure.
611template <typename Stack>
David Benjamin493d5cb2022-04-18 17:20:27 -0400612inline std::enable_if_t<!internal::StackTraits<Stack>::kIsConst, bool>
613PushToStack(Stack *sk,
614 UniquePtr<typename internal::StackTraits<Stack>::Type> elem) {
David Benjamin6e9321f2017-07-25 23:49:58 -0400615 if (!sk_push(reinterpret_cast<_STACK *>(sk), elem.get())) {
616 return false;
617 }
618 // sk_push takes ownership on success.
619 elem.release();
620 return true;
621}
622
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700623BSSL_NAMESPACE_END
David Benjamin01219532017-07-25 22:33:06 -0400624
David Benjaminec783832017-07-25 23:23:03 -0400625// Define begin() and end() for stack types so C++ range for loops work.
626template <typename Stack>
David Benjamina9436132018-09-23 18:36:01 -0500627inline bssl::internal::StackIterator<Stack> begin(const Stack *sk) {
David Benjaminec783832017-07-25 23:23:03 -0400628 return bssl::internal::StackIterator<Stack>(sk, 0);
629}
630
631template <typename Stack>
David Benjamina9436132018-09-23 18:36:01 -0500632inline bssl::internal::StackIterator<Stack> end(const Stack *sk) {
David Benjaminec783832017-07-25 23:23:03 -0400633 return bssl::internal::StackIterator<Stack>(
634 sk, sk_num(reinterpret_cast<const _STACK *>(sk)));
635}
636
David Benjamin01219532017-07-25 22:33:06 -0400637} // extern C++
638#endif
639
David Benjamin4512b792017-08-18 19:21:50 -0400640#endif // OPENSSL_HEADER_STACK_H