blob: cf0300280b26b7dad6dde4f1ed789da08bf984eb [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.
123typedef SAMPLE *(*sk_SAMPLE_copy_func)(SAMPLE *);
124
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
258// its actual type is T *(*)(T *) for some T. Low-level |sk_*| functions will be
David Benjaminfb4e2e02018-09-23 15:59:51 -0500259// passed a type-specific wrapper to call it correctly.
David Benjamin7f857ea2022-06-13 11:47:31 -0400260typedef void *(*OPENSSL_sk_copy_func)(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//
270// TODO(davidben): This type should be |const T *const *|. It is already fixed
271// in OpenSSL 1.1.1, so hopefully we can fix this compatibly.
David Benjamin7f857ea2022-06-13 11:47:31 -0400272typedef int (*OPENSSL_sk_cmp_func)(const void **a, const void **b);
Adam Langley95c29f32014-06-20 12:00:00 -0700273
David Benjamin49e07912022-12-26 10:41:26 -0500274// OPENSSL_sk_delete_if_func is the generic version of
275// |sk_SAMPLE_delete_if_func|.
276typedef int (*OPENSSL_sk_delete_if_func)(void *obj, void *data);
277
David Benjamin167f1762022-06-12 13:47:08 -0400278// The following function types call the above type-erased signatures with the
279// true types.
David Benjamin7f857ea2022-06-13 11:47:31 -0400280typedef void (*OPENSSL_sk_call_free_func)(OPENSSL_sk_free_func, void *);
281typedef void *(*OPENSSL_sk_call_copy_func)(OPENSSL_sk_copy_func, void *);
282typedef int (*OPENSSL_sk_call_cmp_func)(OPENSSL_sk_cmp_func,
283 const void *const *,
284 const void *const *);
David Benjamin49e07912022-12-26 10:41:26 -0500285typedef int (*OPENSSL_sk_call_delete_if_func)(OPENSSL_sk_delete_if_func, void *,
286 void *);
David Benjamin167f1762022-06-12 13:47:08 -0400287
David Benjamin4512b792017-08-18 19:21:50 -0400288// stack_st contains an array of pointers. It is not designed to be used
289// directly, rather the wrapper macros should be used.
Adam Langley95c29f32014-06-20 12:00:00 -0700290typedef struct stack_st {
David Benjamin4512b792017-08-18 19:21:50 -0400291 // num contains the number of valid pointers in |data|.
Adam Langley95c29f32014-06-20 12:00:00 -0700292 size_t num;
293 void **data;
David Benjamin4512b792017-08-18 19:21:50 -0400294 // sorted is non-zero if the values pointed to by |data| are in ascending
295 // order, based on |comp|.
David Benjamin22edd872016-08-04 21:38:40 +0000296 int sorted;
David Benjamin4512b792017-08-18 19:21:50 -0400297 // num_alloc contains the number of pointers allocated in the buffer pointed
298 // to by |data|, which may be larger than |num|.
Adam Langley95c29f32014-06-20 12:00:00 -0700299 size_t num_alloc;
David Benjamin4512b792017-08-18 19:21:50 -0400300 // comp is an optional comparison function.
David Benjamin7f857ea2022-06-13 11:47:31 -0400301 OPENSSL_sk_cmp_func comp;
Adam Langley95c29f32014-06-20 12:00:00 -0700302} _STACK;
303
David Benjamin7f857ea2022-06-13 11:47:31 -0400304// The following are raw stack functions. They implement the corresponding typed
305// |sk_SAMPLE_*| functions generated by |DEFINE_STACK_OF|. Callers shouldn't be
306// using them. Rather, callers should use the typed functions.
307OPENSSL_EXPORT _STACK *sk_new(OPENSSL_sk_cmp_func comp);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700308OPENSSL_EXPORT _STACK *sk_new_null(void);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700309OPENSSL_EXPORT size_t sk_num(const _STACK *sk);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700310OPENSSL_EXPORT void sk_zero(_STACK *sk);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700311OPENSSL_EXPORT void *sk_value(const _STACK *sk, size_t i);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700312OPENSSL_EXPORT void *sk_set(_STACK *sk, size_t i, void *p);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700313OPENSSL_EXPORT void sk_free(_STACK *sk);
David Benjaminfb4e2e02018-09-23 15:59:51 -0500314OPENSSL_EXPORT void sk_pop_free_ex(_STACK *sk,
David Benjamin7f857ea2022-06-13 11:47:31 -0400315 OPENSSL_sk_call_free_func call_free_func,
316 OPENSSL_sk_free_func free_func);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700317OPENSSL_EXPORT size_t sk_insert(_STACK *sk, void *p, size_t where);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700318OPENSSL_EXPORT void *sk_delete(_STACK *sk, size_t where);
David Benjamin8d2f4b92018-09-23 15:11:41 -0500319OPENSSL_EXPORT void *sk_delete_ptr(_STACK *sk, const void *p);
David Benjamin49e07912022-12-26 10:41:26 -0500320OPENSSL_EXPORT void sk_delete_if(_STACK *sk,
321 OPENSSL_sk_call_delete_if_func call_func,
322 OPENSSL_sk_delete_if_func func, void *data);
David Benjamin52483992018-09-23 16:31:03 -0500323OPENSSL_EXPORT int sk_find(const _STACK *sk, size_t *out_index, const void *p,
David Benjamin7f857ea2022-06-13 11:47:31 -0400324 OPENSSL_sk_call_cmp_func call_cmp_func);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700325OPENSSL_EXPORT void *sk_shift(_STACK *sk);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700326OPENSSL_EXPORT size_t sk_push(_STACK *sk, void *p);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700327OPENSSL_EXPORT void *sk_pop(_STACK *sk);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700328OPENSSL_EXPORT _STACK *sk_dup(const _STACK *sk);
David Benjamin7f857ea2022-06-13 11:47:31 -0400329OPENSSL_EXPORT void sk_sort(_STACK *sk, OPENSSL_sk_call_cmp_func call_cmp_func);
Adam Langleyeb7d2ed2014-07-30 16:02:14 -0700330OPENSSL_EXPORT int sk_is_sorted(const _STACK *sk);
David Benjamin7f857ea2022-06-13 11:47:31 -0400331OPENSSL_EXPORT OPENSSL_sk_cmp_func sk_set_cmp_func(_STACK *sk,
332 OPENSSL_sk_cmp_func comp);
David Benjamin167f1762022-06-12 13:47:08 -0400333OPENSSL_EXPORT _STACK *sk_deep_copy(const _STACK *sk,
David Benjamin7f857ea2022-06-13 11:47:31 -0400334 OPENSSL_sk_call_copy_func call_copy_func,
335 OPENSSL_sk_copy_func copy_func,
336 OPENSSL_sk_call_free_func call_free_func,
337 OPENSSL_sk_free_func free_func);
David Benjaminfb4e2e02018-09-23 15:59:51 -0500338
339// sk_pop_free behaves like |sk_pop_free_ex| but performs an invalid function
340// pointer cast. It exists because some existing callers called |sk_pop_free|
341// directly.
342//
343// TODO(davidben): Migrate callers to bssl::UniquePtr and remove this.
David Benjamin7f857ea2022-06-13 11:47:31 -0400344OPENSSL_EXPORT void sk_pop_free(_STACK *sk, OPENSSL_sk_free_func free_func);
David Benjamin01f8a8c2017-04-15 18:12:55 -0400345
David Benjamin01219532017-07-25 22:33:06 -0400346#if !defined(BORINGSSL_NO_CXX)
347extern "C++" {
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700348BSSL_NAMESPACE_BEGIN
David Benjamin01219532017-07-25 22:33:06 -0400349namespace internal {
350template <typename T>
351struct StackTraits {};
352}
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700353BSSL_NAMESPACE_END
David Benjamin01219532017-07-25 22:33:06 -0400354}
355
David Benjaminec783832017-07-25 23:23:03 -0400356#define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) \
357 extern "C++" { \
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700358 BSSL_NAMESPACE_BEGIN \
David Benjaminec783832017-07-25 23:23:03 -0400359 namespace internal { \
360 template <> \
361 struct StackTraits<STACK_OF(name)> { \
362 static constexpr bool kIsStack = true; \
363 using Type = type; \
364 static constexpr bool kIsConst = is_const; \
365 }; \
366 } \
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700367 BSSL_NAMESPACE_END \
David Benjamin01219532017-07-25 22:33:06 -0400368 }
369
370#else
David Benjaminec783832017-07-25 23:23:03 -0400371#define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const)
David Benjamin01219532017-07-25 22:33:06 -0400372#endif
373
David Benjamin7f857ea2022-06-13 11:47:31 -0400374#define BORINGSSL_DEFINE_STACK_OF_IMPL(name, ptrtype, constptrtype) \
375 /* We disable MSVC C4191 in this macro, which warns when pointers are cast \
376 * to the wrong type. While the cast itself is valid, it is often a bug \
377 * because calling it through the cast is UB. However, we never actually \
378 * call functions as |OPENSSL_sk_cmp_func|. The type is just a type-erased \
379 * function pointer. (C does not guarantee function pointers fit in \
380 * |void*|, and GCC will warn on this.) Thus we just disable the false \
381 * positive warning. */ \
382 OPENSSL_MSVC_PRAGMA(warning(push)) \
383 OPENSSL_MSVC_PRAGMA(warning(disable : 4191)) \
384 \
385 DECLARE_STACK_OF(name) \
386 \
387 typedef void (*sk_##name##_free_func)(ptrtype); \
388 typedef ptrtype (*sk_##name##_copy_func)(ptrtype); \
David Benjamin49e07912022-12-26 10:41:26 -0500389 typedef int (*sk_##name##_cmp_func)(constptrtype *, constptrtype *); \
390 typedef int (*sk_##name##_delete_if_func)(ptrtype, void *); \
David Benjamin7f857ea2022-06-13 11:47:31 -0400391 \
392 OPENSSL_INLINE void sk_##name##_call_free_func( \
393 OPENSSL_sk_free_func free_func, void *ptr) { \
394 ((sk_##name##_free_func)free_func)((ptrtype)ptr); \
395 } \
396 \
397 OPENSSL_INLINE void *sk_##name##_call_copy_func( \
398 OPENSSL_sk_copy_func copy_func, void *ptr) { \
399 return (void *)((sk_##name##_copy_func)copy_func)((ptrtype)ptr); \
400 } \
401 \
402 OPENSSL_INLINE int sk_##name##_call_cmp_func(OPENSSL_sk_cmp_func cmp_func, \
403 const void *const *a, \
404 const void *const *b) { \
405 /* The data is actually stored as |void*| pointers, so read the pointer \
406 * as |void*| and then pass the corrected type into the caller-supplied \
407 * function, which expects |constptrtype*|. */ \
408 constptrtype a_ptr = (constptrtype)*a; \
409 constptrtype b_ptr = (constptrtype)*b; \
410 return ((sk_##name##_cmp_func)cmp_func)(&a_ptr, &b_ptr); \
411 } \
412 \
David Benjamin49e07912022-12-26 10:41:26 -0500413 OPENSSL_INLINE int sk_##name##_call_delete_if_func( \
414 OPENSSL_sk_delete_if_func func, void *obj, void *data) { \
415 return ((sk_##name##_delete_if_func)func)((ptrtype)obj, data); \
416 } \
417 \
David Benjamin7f857ea2022-06-13 11:47:31 -0400418 OPENSSL_INLINE STACK_OF(name) *sk_##name##_new(sk_##name##_cmp_func comp) { \
419 return (STACK_OF(name) *)sk_new((OPENSSL_sk_cmp_func)comp); \
420 } \
421 \
422 OPENSSL_INLINE STACK_OF(name) *sk_##name##_new_null(void) { \
423 return (STACK_OF(name) *)sk_new_null(); \
424 } \
425 \
426 OPENSSL_INLINE size_t sk_##name##_num(const STACK_OF(name) *sk) { \
427 return sk_num((const _STACK *)sk); \
428 } \
429 \
430 OPENSSL_INLINE void sk_##name##_zero(STACK_OF(name) *sk) { \
431 sk_zero((_STACK *)sk); \
432 } \
433 \
434 OPENSSL_INLINE ptrtype sk_##name##_value(const STACK_OF(name) *sk, \
435 size_t i) { \
436 return (ptrtype)sk_value((const _STACK *)sk, i); \
437 } \
438 \
439 OPENSSL_INLINE ptrtype sk_##name##_set(STACK_OF(name) *sk, size_t i, \
440 ptrtype p) { \
441 return (ptrtype)sk_set((_STACK *)sk, i, (void *)p); \
442 } \
443 \
444 OPENSSL_INLINE void sk_##name##_free(STACK_OF(name) *sk) { \
445 sk_free((_STACK *)sk); \
446 } \
447 \
448 OPENSSL_INLINE void sk_##name##_pop_free(STACK_OF(name) *sk, \
449 sk_##name##_free_func free_func) { \
450 sk_pop_free_ex((_STACK *)sk, sk_##name##_call_free_func, \
451 (OPENSSL_sk_free_func)free_func); \
452 } \
453 \
454 OPENSSL_INLINE size_t sk_##name##_insert(STACK_OF(name) *sk, ptrtype p, \
455 size_t where) { \
456 return sk_insert((_STACK *)sk, (void *)p, where); \
457 } \
458 \
459 OPENSSL_INLINE ptrtype sk_##name##_delete(STACK_OF(name) *sk, \
460 size_t where) { \
461 return (ptrtype)sk_delete((_STACK *)sk, where); \
462 } \
463 \
464 OPENSSL_INLINE ptrtype sk_##name##_delete_ptr(STACK_OF(name) *sk, \
465 constptrtype p) { \
466 return (ptrtype)sk_delete_ptr((_STACK *)sk, (const void *)p); \
467 } \
468 \
David Benjamin49e07912022-12-26 10:41:26 -0500469 OPENSSL_INLINE void sk_##name##_delete_if( \
470 STACK_OF(name) *sk, sk_##name##_delete_if_func func, void *data) { \
471 sk_delete_if((_STACK *)sk, sk_##name##_call_delete_if_func, \
472 (OPENSSL_sk_delete_if_func)func, data); \
473 } \
474 \
David Benjamin7f857ea2022-06-13 11:47:31 -0400475 OPENSSL_INLINE int sk_##name##_find(const STACK_OF(name) *sk, \
476 size_t *out_index, constptrtype p) { \
477 return sk_find((const _STACK *)sk, out_index, (const void *)p, \
478 sk_##name##_call_cmp_func); \
479 } \
480 \
481 OPENSSL_INLINE ptrtype sk_##name##_shift(STACK_OF(name) *sk) { \
482 return (ptrtype)sk_shift((_STACK *)sk); \
483 } \
484 \
485 OPENSSL_INLINE size_t sk_##name##_push(STACK_OF(name) *sk, ptrtype p) { \
486 return sk_push((_STACK *)sk, (void *)p); \
487 } \
488 \
489 OPENSSL_INLINE ptrtype sk_##name##_pop(STACK_OF(name) *sk) { \
490 return (ptrtype)sk_pop((_STACK *)sk); \
491 } \
492 \
493 OPENSSL_INLINE STACK_OF(name) *sk_##name##_dup(const STACK_OF(name) *sk) { \
494 return (STACK_OF(name) *)sk_dup((const _STACK *)sk); \
495 } \
496 \
497 OPENSSL_INLINE void sk_##name##_sort(STACK_OF(name) *sk) { \
498 sk_sort((_STACK *)sk, sk_##name##_call_cmp_func); \
499 } \
500 \
501 OPENSSL_INLINE int sk_##name##_is_sorted(const STACK_OF(name) *sk) { \
502 return sk_is_sorted((const _STACK *)sk); \
503 } \
504 \
505 OPENSSL_INLINE sk_##name##_cmp_func sk_##name##_set_cmp_func( \
506 STACK_OF(name) *sk, sk_##name##_cmp_func comp) { \
507 return (sk_##name##_cmp_func)sk_set_cmp_func((_STACK *)sk, \
508 (OPENSSL_sk_cmp_func)comp); \
509 } \
510 \
511 OPENSSL_INLINE STACK_OF(name) *sk_##name##_deep_copy( \
512 const STACK_OF(name) *sk, sk_##name##_copy_func copy_func, \
513 sk_##name##_free_func free_func) { \
514 return (STACK_OF(name) *)sk_deep_copy( \
515 (const _STACK *)sk, sk_##name##_call_copy_func, \
516 (OPENSSL_sk_copy_func)copy_func, sk_##name##_call_free_func, \
517 (OPENSSL_sk_free_func)free_func); \
518 } \
519 \
David Benjamin167f1762022-06-12 13:47:08 -0400520 OPENSSL_MSVC_PRAGMA(warning(pop))
David Benjamin01f8a8c2017-04-15 18:12:55 -0400521
David Benjamin35b4a122018-07-14 17:04:41 -0400522
David Benjamin7f857ea2022-06-13 11:47:31 -0400523// Built-in stacks.
David Benjamin01f8a8c2017-04-15 18:12:55 -0400524
David Benjamin01f8a8c2017-04-15 18:12:55 -0400525typedef char *OPENSSL_STRING;
526
527DEFINE_STACK_OF(void)
David Benjamin1500ad02022-06-13 12:33:07 -0400528DEFINE_NAMED_STACK_OF(OPENSSL_STRING, char)
David Benjamin01f8a8c2017-04-15 18:12:55 -0400529
530
Adam Langley95c29f32014-06-20 12:00:00 -0700531#if defined(__cplusplus)
David Benjamin4512b792017-08-18 19:21:50 -0400532} // extern C
Adam Langley95c29f32014-06-20 12:00:00 -0700533#endif
534
David Benjamin01219532017-07-25 22:33:06 -0400535#if !defined(BORINGSSL_NO_CXX)
536extern "C++" {
537
538#include <type_traits>
539
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700540BSSL_NAMESPACE_BEGIN
David Benjamin01219532017-07-25 22:33:06 -0400541
542namespace internal {
543
544// Stacks defined with |DEFINE_CONST_STACK_OF| are freed with |sk_free|.
545template <typename Stack>
David Benjamin493d5cb2022-04-18 17:20:27 -0400546struct DeleterImpl<Stack, std::enable_if_t<StackTraits<Stack>::kIsConst>> {
David Benjamin01219532017-07-25 22:33:06 -0400547 static void Free(Stack *sk) { sk_free(reinterpret_cast<_STACK *>(sk)); }
548};
549
550// Stacks defined with |DEFINE_STACK_OF| are freed with |sk_pop_free| and the
551// corresponding type's deleter.
552template <typename Stack>
David Benjamin493d5cb2022-04-18 17:20:27 -0400553struct DeleterImpl<Stack, std::enable_if_t<!StackTraits<Stack>::kIsConst>> {
David Benjamin01219532017-07-25 22:33:06 -0400554 static void Free(Stack *sk) {
David Benjaminfb4e2e02018-09-23 15:59:51 -0500555 // sk_FOO_pop_free is defined by macros and bound by name, so we cannot
556 // access it from C++ here.
557 using Type = typename StackTraits<Stack>::Type;
558 sk_pop_free_ex(reinterpret_cast<_STACK *>(sk),
David Benjamin7f857ea2022-06-13 11:47:31 -0400559 [](OPENSSL_sk_free_func /* unused */, void *ptr) {
David Benjaminfb4e2e02018-09-23 15:59:51 -0500560 DeleterImpl<Type>::Free(reinterpret_cast<Type *>(ptr));
561 },
562 nullptr);
David Benjamin01219532017-07-25 22:33:06 -0400563 }
564};
565
David Benjaminec783832017-07-25 23:23:03 -0400566template <typename Stack>
567class StackIteratorImpl {
568 public:
569 using Type = typename StackTraits<Stack>::Type;
570 // Iterators must be default-constructable.
571 StackIteratorImpl() : sk_(nullptr), idx_(0) {}
572 StackIteratorImpl(const Stack *sk, size_t idx) : sk_(sk), idx_(idx) {}
573
574 bool operator==(StackIteratorImpl other) const {
575 return sk_ == other.sk_ && idx_ == other.idx_;
576 }
577 bool operator!=(StackIteratorImpl other) const {
578 return !(*this == other);
579 }
580
581 Type *operator*() const {
582 return reinterpret_cast<Type *>(
583 sk_value(reinterpret_cast<const _STACK *>(sk_), idx_));
584 }
585
586 StackIteratorImpl &operator++(/* prefix */) {
587 idx_++;
588 return *this;
589 }
590
591 StackIteratorImpl operator++(int /* postfix */) {
592 StackIteratorImpl copy(*this);
593 ++(*this);
594 return copy;
595 }
596
597 private:
598 const Stack *sk_;
599 size_t idx_;
600};
601
602template <typename Stack>
David Benjamin493d5cb2022-04-18 17:20:27 -0400603using StackIterator =
604 std::enable_if_t<StackTraits<Stack>::kIsStack, StackIteratorImpl<Stack>>;
David Benjaminec783832017-07-25 23:23:03 -0400605
David Benjamin01219532017-07-25 22:33:06 -0400606} // namespace internal
607
David Benjamin6e9321f2017-07-25 23:49:58 -0400608// PushToStack pushes |elem| to |sk|. It returns true on success and false on
609// allocation failure.
610template <typename Stack>
David Benjamin493d5cb2022-04-18 17:20:27 -0400611inline std::enable_if_t<!internal::StackTraits<Stack>::kIsConst, bool>
612PushToStack(Stack *sk,
613 UniquePtr<typename internal::StackTraits<Stack>::Type> elem) {
David Benjamin6e9321f2017-07-25 23:49:58 -0400614 if (!sk_push(reinterpret_cast<_STACK *>(sk), elem.get())) {
615 return false;
616 }
617 // sk_push takes ownership on success.
618 elem.release();
619 return true;
620}
621
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700622BSSL_NAMESPACE_END
David Benjamin01219532017-07-25 22:33:06 -0400623
David Benjaminec783832017-07-25 23:23:03 -0400624// Define begin() and end() for stack types so C++ range for loops work.
625template <typename Stack>
David Benjamina9436132018-09-23 18:36:01 -0500626inline bssl::internal::StackIterator<Stack> begin(const Stack *sk) {
David Benjaminec783832017-07-25 23:23:03 -0400627 return bssl::internal::StackIterator<Stack>(sk, 0);
628}
629
630template <typename Stack>
David Benjamina9436132018-09-23 18:36:01 -0500631inline bssl::internal::StackIterator<Stack> end(const Stack *sk) {
David Benjaminec783832017-07-25 23:23:03 -0400632 return bssl::internal::StackIterator<Stack>(
633 sk, sk_num(reinterpret_cast<const _STACK *>(sk)));
634}
635
David Benjamin01219532017-07-25 22:33:06 -0400636} // extern C++
637#endif
638
David Benjamin4512b792017-08-18 19:21:50 -0400639#endif // OPENSSL_HEADER_STACK_H