blob: 0eccb2f0cb5742a99a180bfad61997ff6e9b64b4 [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*|.
David Benjaminaf0739f2023-01-09 10:03:02 -0800130typedef int (*sk_SAMPLE_cmp_func)(const SAMPLE *const *a,
131 const SAMPLE *const *b);
David Benjamin7f857ea2022-06-13 11:47:31 -0400132
133// sk_SAMPLE_new creates a new, empty stack with the given comparison function,
134// which may be NULL. It returns the new stack or NULL on allocation failure.
135STACK_OF(SAMPLE) *sk_SAMPLE_new(sk_SAMPLE_cmp_func comp);
136
137// sk_SAMPLE_new_null creates a new, empty stack. It returns the new stack or
138// NULL on allocation failure.
139STACK_OF(SAMPLE) *sk_SAMPLE_new_null(void);
140
David Benjamin8c7e9252023-05-23 11:45:09 -0400141// sk_SAMPLE_num returns the number of elements in |sk|. It is safe to cast this
David Benjamin821fe332024-03-22 13:16:03 +1000142// value to |int|. |sk| is guaranteed to have at most |INT_MAX| elements. If
143// |sk| is NULL, it is treated as the empty list and this function returns zero.
David Benjamin7f857ea2022-06-13 11:47:31 -0400144size_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
David Benjamin821fe332024-03-22 13:16:03 +1000151// range. If |sk| is NULL, it is treated as an empty list and the function
152// returns NULL.
David Benjamin7f857ea2022-06-13 11:47:31 -0400153SAMPLE *sk_SAMPLE_value(const STACK_OF(SAMPLE) *sk, size_t i);
154
155// sk_SAMPLE_set sets the |i|th pointer in |sk| to |p| and returns |p|. If |i|
156// is out of range, it returns NULL.
157SAMPLE *sk_SAMPLE_set(STACK_OF(SAMPLE) *sk, size_t i, SAMPLE *p);
158
159// sk_SAMPLE_free frees |sk|, but does nothing to free the individual elements.
160// Use |sk_SAMPLE_pop_free| to also free the elements.
161void sk_SAMPLE_free(STACK_OF(SAMPLE) *sk);
162
163// sk_SAMPLE_pop_free calls |free_func| on each element in |sk| and then
164// frees the stack itself.
165void sk_SAMPLE_pop_free(STACK_OF(SAMPLE) *sk, sk_SAMPLE_free_func free_func);
166
167// sk_SAMPLE_insert inserts |p| into the stack at index |where|, moving existing
168// elements if needed. It returns the length of the new stack, or zero on
169// error.
170size_t sk_SAMPLE_insert(STACK_OF(SAMPLE) *sk, SAMPLE *p, size_t where);
171
172// sk_SAMPLE_delete removes the pointer at index |where|, moving other elements
173// down if needed. It returns the removed pointer, or NULL if |where| is out of
174// range.
175SAMPLE *sk_SAMPLE_delete(STACK_OF(SAMPLE) *sk, size_t where);
176
177// sk_SAMPLE_delete_ptr removes, at most, one instance of |p| from |sk| based on
178// pointer equality. If an instance of |p| is found then |p| is returned,
179// otherwise it returns NULL.
180SAMPLE *sk_SAMPLE_delete_ptr(STACK_OF(SAMPLE) *sk, const SAMPLE *p);
181
David Benjamin49e07912022-12-26 10:41:26 -0500182// sk_SAMPLE_delete_if_func is the callback function for |sk_SAMPLE_delete_if|.
183// It should return one to remove |p| and zero to keep it.
184typedef int (*sk_SAMPLE_delete_if_func)(SAMPLE *p, void *data);
185
186// sk_SAMPLE_delete_if calls |func| with each element of |sk| and removes the
187// entries where |func| returned one. This function does not free or return
188// removed pointers so, if |sk| owns its contents, |func| should release the
189// pointers prior to returning one.
190void sk_SAMPLE_delete_if(STACK_OF(SAMPLE) *sk, sk_SAMPLE_delete_if_func func,
191 void *data);
192
David Benjamin7f857ea2022-06-13 11:47:31 -0400193// sk_SAMPLE_find find the first value in |sk| equal to |p|. |sk|'s comparison
194// function determines equality, or pointer equality if |sk| has no comparison
195// function.
196//
197// If the stack is sorted (see |sk_SAMPLE_sort|), this function uses a binary
198// search. Otherwise it performs a linear search. If it finds a matching
199// element, it writes the index to |*out_index| (if |out_index| is not NULL) and
David Benjamin821fe332024-03-22 13:16:03 +1000200// returns one. Otherwise, it returns zero. If |sk| is NULL, it is treated as
201// the empty list and the function returns zero.
David Benjamin7f857ea2022-06-13 11:47:31 -0400202//
203// Note this differs from OpenSSL. The type signature is slightly different, and
204// OpenSSL's version will implicitly sort |sk| if it has a comparison function
205// defined.
206int sk_SAMPLE_find(const STACK_OF(SAMPLE) *sk, size_t *out_index,
207 const SAMPLE *p);
208
209// sk_SAMPLE_shift removes and returns the first element in |sk|, or NULL if
210// |sk| is empty.
211SAMPLE *sk_SAMPLE_shift(STACK_OF(SAMPLE) *sk);
212
213// sk_SAMPLE_push appends |p| to |sk| and returns the length of the new stack,
214// or 0 on allocation failure.
215size_t sk_SAMPLE_push(STACK_OF(SAMPLE) *sk, SAMPLE *p);
216
217// sk_SAMPLE_pop removes and returns the last element of |sk|, or NULL if |sk|
218// is empty.
219SAMPLE *sk_SAMPLE_pop(STACK_OF(SAMPLE) *sk);
220
221// sk_SAMPLE_dup performs a shallow copy of a stack and returns the new stack,
222// or NULL on error. Use |sk_SAMPLE_deep_copy| to also copy the elements.
223STACK_OF(SAMPLE) *sk_SAMPLE_dup(const STACK_OF(SAMPLE) *sk);
224
225// sk_SAMPLE_sort sorts the elements of |sk| into ascending order based on the
226// comparison function. The stack maintains a "sorted" flag and sorting an
227// already sorted stack is a no-op.
228void sk_SAMPLE_sort(STACK_OF(SAMPLE) *sk);
229
230// sk_SAMPLE_is_sorted returns one if |sk| is known to be sorted and zero
231// otherwise.
232int sk_SAMPLE_is_sorted(const STACK_OF(SAMPLE) *sk);
233
234// sk_SAMPLE_set_cmp_func sets the comparison function to be used by |sk| and
235// returns the previous one.
236sk_SAMPLE_cmp_func sk_SAMPLE_set_cmp_func(STACK_OF(SAMPLE) *sk,
237 sk_SAMPLE_cmp_func comp);
238
239// sk_SAMPLE_deep_copy performs a copy of |sk| and of each of the non-NULL
240// elements in |sk| by using |copy_func|. If an error occurs, it calls
241// |free_func| to free any copies already made and returns NULL.
242STACK_OF(SAMPLE) *sk_SAMPLE_deep_copy(const STACK_OF(SAMPLE) *sk,
243 sk_SAMPLE_copy_func copy_func,
244 sk_SAMPLE_free_func free_func);
245
246#endif // Sample
247
248
249// Private functions.
250//
David Benjamin99d3c222023-06-03 23:00:40 -0400251// The |sk_*| functions generated above are implemented internally using the
252// type-erased functions below. Callers should use the typed wrappers instead.
253// When using the type-erased functions, callers are responsible for ensuring
254// the underlying types are correct. Casting pointers to the wrong types will
255// result in memory errors.
David Benjamin7f857ea2022-06-13 11:47:31 -0400256
257// OPENSSL_sk_free_func is a function that frees an element in a stack. Note its
David Benjaminfb4e2e02018-09-23 15:59:51 -0500258// actual type is void (*)(T *) for some T. Low-level |sk_*| functions will be
259// passed a type-specific wrapper to call it correctly.
David Benjamin7f857ea2022-06-13 11:47:31 -0400260typedef void (*OPENSSL_sk_free_func)(void *ptr);
David Benjaminfb4e2e02018-09-23 15:59:51 -0500261
David Benjamin7f857ea2022-06-13 11:47:31 -0400262// OPENSSL_sk_copy_func is a function that copies an element in a stack. Note
David Benjamindf8a55b2023-01-04 15:52:36 -0800263// its actual type is T *(*)(const T *) for some T. Low-level |sk_*| functions
264// will be passed a type-specific wrapper to call it correctly.
265typedef void *(*OPENSSL_sk_copy_func)(const void *ptr);
David Benjaminfb4e2e02018-09-23 15:59:51 -0500266
David Benjamin7f857ea2022-06-13 11:47:31 -0400267// OPENSSL_sk_cmp_func is a comparison function that returns a value < 0, 0 or >
268// 0 if |*a| is less than, equal to or greater than |*b|, respectively. Note
269// the extra indirection - the function is given a pointer to a pointer to the
David Benjamin4512b792017-08-18 19:21:50 -0400270// element. This differs from the usual qsort/bsearch comparison function.
David Benjamin52483992018-09-23 16:31:03 -0500271//
David Benjaminaf0739f2023-01-09 10:03:02 -0800272// Note its actual type is |int (*)(const T *const *a, const T *const *b)|.
273// Low-level |sk_*| functions will be passed a type-specific wrapper to call it
274// correctly.
275typedef int (*OPENSSL_sk_cmp_func)(const void *const *a, const void *const *b);
Adam Langley95c29f32014-06-20 12:00:00 -0700276
David Benjamin49e07912022-12-26 10:41:26 -0500277// OPENSSL_sk_delete_if_func is the generic version of
278// |sk_SAMPLE_delete_if_func|.
279typedef int (*OPENSSL_sk_delete_if_func)(void *obj, void *data);
280
David Benjamin167f1762022-06-12 13:47:08 -0400281// The following function types call the above type-erased signatures with the
282// true types.
David Benjamin7f857ea2022-06-13 11:47:31 -0400283typedef void (*OPENSSL_sk_call_free_func)(OPENSSL_sk_free_func, void *);
David Benjamindf8a55b2023-01-04 15:52:36 -0800284typedef void *(*OPENSSL_sk_call_copy_func)(OPENSSL_sk_copy_func, const void *);
David Benjamin9d489022023-06-06 19:34:39 -0400285typedef int (*OPENSSL_sk_call_cmp_func)(OPENSSL_sk_cmp_func, const void *,
286 const void *);
David Benjamin49e07912022-12-26 10:41:26 -0500287typedef int (*OPENSSL_sk_call_delete_if_func)(OPENSSL_sk_delete_if_func, void *,
288 void *);
David Benjamin167f1762022-06-12 13:47:08 -0400289
David Benjamin99d3c222023-06-03 23:00:40 -0400290// An OPENSSL_STACK contains an array of pointers. It is not designed to be used
David Benjamin4512b792017-08-18 19:21:50 -0400291// directly, rather the wrapper macros should be used.
David Benjamin99d3c222023-06-03 23:00:40 -0400292typedef struct stack_st OPENSSL_STACK;
Adam Langley95c29f32014-06-20 12:00:00 -0700293
David Benjamin7f857ea2022-06-13 11:47:31 -0400294// The following are raw stack functions. They implement the corresponding typed
295// |sk_SAMPLE_*| functions generated by |DEFINE_STACK_OF|. Callers shouldn't be
296// using them. Rather, callers should use the typed functions.
David Benjamin99d3c222023-06-03 23:00:40 -0400297OPENSSL_EXPORT OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_cmp_func comp);
298OPENSSL_EXPORT OPENSSL_STACK *OPENSSL_sk_new_null(void);
299OPENSSL_EXPORT size_t OPENSSL_sk_num(const OPENSSL_STACK *sk);
300OPENSSL_EXPORT void OPENSSL_sk_zero(OPENSSL_STACK *sk);
301OPENSSL_EXPORT void *OPENSSL_sk_value(const OPENSSL_STACK *sk, size_t i);
302OPENSSL_EXPORT void *OPENSSL_sk_set(OPENSSL_STACK *sk, size_t i, void *p);
303OPENSSL_EXPORT void OPENSSL_sk_free(OPENSSL_STACK *sk);
304OPENSSL_EXPORT void OPENSSL_sk_pop_free_ex(
305 OPENSSL_STACK *sk, OPENSSL_sk_call_free_func call_free_func,
306 OPENSSL_sk_free_func free_func);
307OPENSSL_EXPORT size_t OPENSSL_sk_insert(OPENSSL_STACK *sk, void *p,
308 size_t where);
309OPENSSL_EXPORT void *OPENSSL_sk_delete(OPENSSL_STACK *sk, size_t where);
310OPENSSL_EXPORT void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *sk, const void *p);
311OPENSSL_EXPORT void OPENSSL_sk_delete_if(
312 OPENSSL_STACK *sk, OPENSSL_sk_call_delete_if_func call_func,
313 OPENSSL_sk_delete_if_func func, void *data);
314OPENSSL_EXPORT int OPENSSL_sk_find(const OPENSSL_STACK *sk, size_t *out_index,
315 const void *p,
316 OPENSSL_sk_call_cmp_func call_cmp_func);
317OPENSSL_EXPORT void *OPENSSL_sk_shift(OPENSSL_STACK *sk);
318OPENSSL_EXPORT size_t OPENSSL_sk_push(OPENSSL_STACK *sk, void *p);
319OPENSSL_EXPORT void *OPENSSL_sk_pop(OPENSSL_STACK *sk);
320OPENSSL_EXPORT OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk);
321OPENSSL_EXPORT void OPENSSL_sk_sort(OPENSSL_STACK *sk,
322 OPENSSL_sk_call_cmp_func call_cmp_func);
323OPENSSL_EXPORT int OPENSSL_sk_is_sorted(const OPENSSL_STACK *sk);
324OPENSSL_EXPORT OPENSSL_sk_cmp_func
325OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_cmp_func comp);
326OPENSSL_EXPORT OPENSSL_STACK *OPENSSL_sk_deep_copy(
327 const OPENSSL_STACK *sk, OPENSSL_sk_call_copy_func call_copy_func,
328 OPENSSL_sk_copy_func copy_func, OPENSSL_sk_call_free_func call_free_func,
329 OPENSSL_sk_free_func free_func);
330
331
332// Deprecated private functions (hidden).
333//
334// TODO(crbug.com/boringssl/499): Migrate callers to the typed wrappers, or at
335// least the new names and remove the old ones.
David Benjamin690dcdf2023-07-11 13:51:59 -0400336//
337// TODO(b/290792019, b/290785937): Ideally these would at least be inline
338// functions, so we do not squat the symbols.
David Benjamin99d3c222023-06-03 23:00:40 -0400339
340typedef OPENSSL_STACK _STACK;
341
David Benjamin690dcdf2023-07-11 13:51:59 -0400342// The following functions call the corresponding |OPENSSL_sk_*| function.
David Benjaminf04fbf52023-07-20 11:31:07 -0400343OPENSSL_EXPORT OPENSSL_DEPRECATED OPENSSL_STACK *sk_new_null(void);
344OPENSSL_EXPORT OPENSSL_DEPRECATED size_t sk_num(const OPENSSL_STACK *sk);
345OPENSSL_EXPORT OPENSSL_DEPRECATED void *sk_value(const OPENSSL_STACK *sk,
346 size_t i);
347OPENSSL_EXPORT OPENSSL_DEPRECATED void sk_free(OPENSSL_STACK *sk);
348OPENSSL_EXPORT OPENSSL_DEPRECATED size_t sk_push(OPENSSL_STACK *sk, void *p);
349OPENSSL_EXPORT OPENSSL_DEPRECATED void *sk_pop(OPENSSL_STACK *sk);
David Benjaminfb4e2e02018-09-23 15:59:51 -0500350
David Benjaminb1ff33d2023-07-20 10:53:36 -0400351// sk_pop_free_ex calls |OPENSSL_sk_pop_free_ex|.
352//
353// TODO(b/291994116): Remove this.
David Benjaminf04fbf52023-07-20 11:31:07 -0400354OPENSSL_EXPORT OPENSSL_DEPRECATED void sk_pop_free_ex(
355 OPENSSL_STACK *sk, OPENSSL_sk_call_free_func call_free_func,
356 OPENSSL_sk_free_func free_func);
David Benjaminb1ff33d2023-07-20 10:53:36 -0400357
358// sk_pop_free behaves like |OPENSSL_sk_pop_free_ex| but performs an invalid
359// function pointer cast. It exists because some existing callers called
360// |sk_pop_free| directly.
David Benjaminfb4e2e02018-09-23 15:59:51 -0500361//
362// TODO(davidben): Migrate callers to bssl::UniquePtr and remove this.
David Benjaminf04fbf52023-07-20 11:31:07 -0400363OPENSSL_EXPORT OPENSSL_DEPRECATED void sk_pop_free(
364 OPENSSL_STACK *sk, OPENSSL_sk_free_func free_func);
David Benjamin99d3c222023-06-03 23:00:40 -0400365
David Benjamin01f8a8c2017-04-15 18:12:55 -0400366
David Benjamin01219532017-07-25 22:33:06 -0400367#if !defined(BORINGSSL_NO_CXX)
368extern "C++" {
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700369BSSL_NAMESPACE_BEGIN
David Benjamin01219532017-07-25 22:33:06 -0400370namespace internal {
371template <typename T>
372struct StackTraits {};
373}
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700374BSSL_NAMESPACE_END
David Benjamin01219532017-07-25 22:33:06 -0400375}
376
David Benjaminec783832017-07-25 23:23:03 -0400377#define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) \
378 extern "C++" { \
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700379 BSSL_NAMESPACE_BEGIN \
David Benjaminec783832017-07-25 23:23:03 -0400380 namespace internal { \
381 template <> \
382 struct StackTraits<STACK_OF(name)> { \
383 static constexpr bool kIsStack = true; \
384 using Type = type; \
385 static constexpr bool kIsConst = is_const; \
386 }; \
387 } \
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700388 BSSL_NAMESPACE_END \
David Benjamin01219532017-07-25 22:33:06 -0400389 }
390
391#else
David Benjaminec783832017-07-25 23:23:03 -0400392#define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const)
David Benjamin01219532017-07-25 22:33:06 -0400393#endif
394
David Benjamin99d3c222023-06-03 23:00:40 -0400395#define BORINGSSL_DEFINE_STACK_OF_IMPL(name, ptrtype, constptrtype) \
396 /* We disable MSVC C4191 in this macro, which warns when pointers are cast \
397 * to the wrong type. While the cast itself is valid, it is often a bug \
398 * because calling it through the cast is UB. However, we never actually \
399 * call functions as |OPENSSL_sk_cmp_func|. The type is just a type-erased \
400 * function pointer. (C does not guarantee function pointers fit in \
401 * |void*|, and GCC will warn on this.) Thus we just disable the false \
402 * positive warning. */ \
403 OPENSSL_MSVC_PRAGMA(warning(push)) \
404 OPENSSL_MSVC_PRAGMA(warning(disable : 4191)) \
Brian Ledger68c6fd82024-04-02 15:17:16 -0400405 OPENSSL_CLANG_PRAGMA("clang diagnostic push") \
406 OPENSSL_CLANG_PRAGMA("clang diagnostic ignored \"-Wunknown-warning-option\"") \
407 OPENSSL_CLANG_PRAGMA("clang diagnostic ignored \"-Wcast-function-type-strict\"") \
David Benjamin99d3c222023-06-03 23:00:40 -0400408 \
409 DECLARE_STACK_OF(name) \
410 \
411 typedef void (*sk_##name##_free_func)(ptrtype); \
412 typedef ptrtype (*sk_##name##_copy_func)(constptrtype); \
413 typedef int (*sk_##name##_cmp_func)(constptrtype const *, \
414 constptrtype const *); \
415 typedef int (*sk_##name##_delete_if_func)(ptrtype, void *); \
416 \
417 OPENSSL_INLINE void sk_##name##_call_free_func( \
418 OPENSSL_sk_free_func free_func, void *ptr) { \
419 ((sk_##name##_free_func)free_func)((ptrtype)ptr); \
420 } \
421 \
422 OPENSSL_INLINE void *sk_##name##_call_copy_func( \
423 OPENSSL_sk_copy_func copy_func, const void *ptr) { \
424 return (void *)((sk_##name##_copy_func)copy_func)((constptrtype)ptr); \
425 } \
426 \
427 OPENSSL_INLINE int sk_##name##_call_cmp_func(OPENSSL_sk_cmp_func cmp_func, \
David Benjamin9d489022023-06-06 19:34:39 -0400428 const void *a, const void *b) { \
429 constptrtype a_ptr = (constptrtype)a; \
430 constptrtype b_ptr = (constptrtype)b; \
431 /* |cmp_func| expects an extra layer of pointers to match qsort. */ \
David Benjamin99d3c222023-06-03 23:00:40 -0400432 return ((sk_##name##_cmp_func)cmp_func)(&a_ptr, &b_ptr); \
433 } \
434 \
435 OPENSSL_INLINE int sk_##name##_call_delete_if_func( \
436 OPENSSL_sk_delete_if_func func, void *obj, void *data) { \
437 return ((sk_##name##_delete_if_func)func)((ptrtype)obj, data); \
438 } \
439 \
440 OPENSSL_INLINE STACK_OF(name) *sk_##name##_new(sk_##name##_cmp_func comp) { \
441 return (STACK_OF(name) *)OPENSSL_sk_new((OPENSSL_sk_cmp_func)comp); \
442 } \
443 \
444 OPENSSL_INLINE STACK_OF(name) *sk_##name##_new_null(void) { \
445 return (STACK_OF(name) *)OPENSSL_sk_new_null(); \
446 } \
447 \
448 OPENSSL_INLINE size_t sk_##name##_num(const STACK_OF(name) *sk) { \
449 return OPENSSL_sk_num((const OPENSSL_STACK *)sk); \
450 } \
451 \
452 OPENSSL_INLINE void sk_##name##_zero(STACK_OF(name) *sk) { \
453 OPENSSL_sk_zero((OPENSSL_STACK *)sk); \
454 } \
455 \
456 OPENSSL_INLINE ptrtype sk_##name##_value(const STACK_OF(name) *sk, \
457 size_t i) { \
458 return (ptrtype)OPENSSL_sk_value((const OPENSSL_STACK *)sk, i); \
459 } \
460 \
461 OPENSSL_INLINE ptrtype sk_##name##_set(STACK_OF(name) *sk, size_t i, \
462 ptrtype p) { \
463 return (ptrtype)OPENSSL_sk_set((OPENSSL_STACK *)sk, i, (void *)p); \
464 } \
465 \
466 OPENSSL_INLINE void sk_##name##_free(STACK_OF(name) *sk) { \
467 OPENSSL_sk_free((OPENSSL_STACK *)sk); \
468 } \
469 \
470 OPENSSL_INLINE void sk_##name##_pop_free(STACK_OF(name) *sk, \
471 sk_##name##_free_func free_func) { \
472 OPENSSL_sk_pop_free_ex((OPENSSL_STACK *)sk, sk_##name##_call_free_func, \
473 (OPENSSL_sk_free_func)free_func); \
474 } \
475 \
476 OPENSSL_INLINE size_t sk_##name##_insert(STACK_OF(name) *sk, ptrtype p, \
477 size_t where) { \
478 return OPENSSL_sk_insert((OPENSSL_STACK *)sk, (void *)p, where); \
479 } \
480 \
481 OPENSSL_INLINE ptrtype sk_##name##_delete(STACK_OF(name) *sk, \
482 size_t where) { \
483 return (ptrtype)OPENSSL_sk_delete((OPENSSL_STACK *)sk, where); \
484 } \
485 \
486 OPENSSL_INLINE ptrtype sk_##name##_delete_ptr(STACK_OF(name) *sk, \
487 constptrtype p) { \
488 return (ptrtype)OPENSSL_sk_delete_ptr((OPENSSL_STACK *)sk, \
489 (const void *)p); \
490 } \
491 \
492 OPENSSL_INLINE void sk_##name##_delete_if( \
493 STACK_OF(name) *sk, sk_##name##_delete_if_func func, void *data) { \
494 OPENSSL_sk_delete_if((OPENSSL_STACK *)sk, sk_##name##_call_delete_if_func, \
495 (OPENSSL_sk_delete_if_func)func, data); \
496 } \
497 \
498 OPENSSL_INLINE int sk_##name##_find(const STACK_OF(name) *sk, \
499 size_t *out_index, constptrtype p) { \
500 return OPENSSL_sk_find((const OPENSSL_STACK *)sk, out_index, \
501 (const void *)p, sk_##name##_call_cmp_func); \
502 } \
503 \
504 OPENSSL_INLINE ptrtype sk_##name##_shift(STACK_OF(name) *sk) { \
505 return (ptrtype)OPENSSL_sk_shift((OPENSSL_STACK *)sk); \
506 } \
507 \
508 OPENSSL_INLINE size_t sk_##name##_push(STACK_OF(name) *sk, ptrtype p) { \
509 return OPENSSL_sk_push((OPENSSL_STACK *)sk, (void *)p); \
510 } \
511 \
512 OPENSSL_INLINE ptrtype sk_##name##_pop(STACK_OF(name) *sk) { \
513 return (ptrtype)OPENSSL_sk_pop((OPENSSL_STACK *)sk); \
514 } \
515 \
516 OPENSSL_INLINE STACK_OF(name) *sk_##name##_dup(const STACK_OF(name) *sk) { \
517 return (STACK_OF(name) *)OPENSSL_sk_dup((const OPENSSL_STACK *)sk); \
518 } \
519 \
520 OPENSSL_INLINE void sk_##name##_sort(STACK_OF(name) *sk) { \
521 OPENSSL_sk_sort((OPENSSL_STACK *)sk, sk_##name##_call_cmp_func); \
522 } \
523 \
524 OPENSSL_INLINE int sk_##name##_is_sorted(const STACK_OF(name) *sk) { \
525 return OPENSSL_sk_is_sorted((const OPENSSL_STACK *)sk); \
526 } \
527 \
528 OPENSSL_INLINE sk_##name##_cmp_func sk_##name##_set_cmp_func( \
529 STACK_OF(name) *sk, sk_##name##_cmp_func comp) { \
530 return (sk_##name##_cmp_func)OPENSSL_sk_set_cmp_func( \
531 (OPENSSL_STACK *)sk, (OPENSSL_sk_cmp_func)comp); \
532 } \
533 \
534 OPENSSL_INLINE STACK_OF(name) *sk_##name##_deep_copy( \
535 const STACK_OF(name) *sk, sk_##name##_copy_func copy_func, \
536 sk_##name##_free_func free_func) { \
537 return (STACK_OF(name) *)OPENSSL_sk_deep_copy( \
538 (const OPENSSL_STACK *)sk, sk_##name##_call_copy_func, \
539 (OPENSSL_sk_copy_func)copy_func, sk_##name##_call_free_func, \
540 (OPENSSL_sk_free_func)free_func); \
541 } \
542 \
Brian Ledger68c6fd82024-04-02 15:17:16 -0400543 OPENSSL_CLANG_PRAGMA("clang diagnostic pop") \
David Benjamin167f1762022-06-12 13:47:08 -0400544 OPENSSL_MSVC_PRAGMA(warning(pop))
David Benjamin01f8a8c2017-04-15 18:12:55 -0400545
David Benjamin35b4a122018-07-14 17:04:41 -0400546
David Benjamin7f857ea2022-06-13 11:47:31 -0400547// Built-in stacks.
David Benjamin01f8a8c2017-04-15 18:12:55 -0400548
David Benjamin01f8a8c2017-04-15 18:12:55 -0400549typedef char *OPENSSL_STRING;
550
551DEFINE_STACK_OF(void)
David Benjamin1500ad02022-06-13 12:33:07 -0400552DEFINE_NAMED_STACK_OF(OPENSSL_STRING, char)
David Benjamin01f8a8c2017-04-15 18:12:55 -0400553
554
Adam Langley95c29f32014-06-20 12:00:00 -0700555#if defined(__cplusplus)
David Benjamin4512b792017-08-18 19:21:50 -0400556} // extern C
Adam Langley95c29f32014-06-20 12:00:00 -0700557#endif
558
David Benjamin01219532017-07-25 22:33:06 -0400559#if !defined(BORINGSSL_NO_CXX)
560extern "C++" {
561
562#include <type_traits>
563
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700564BSSL_NAMESPACE_BEGIN
David Benjamin01219532017-07-25 22:33:06 -0400565
566namespace internal {
567
568// Stacks defined with |DEFINE_CONST_STACK_OF| are freed with |sk_free|.
569template <typename Stack>
David Benjamin493d5cb2022-04-18 17:20:27 -0400570struct DeleterImpl<Stack, std::enable_if_t<StackTraits<Stack>::kIsConst>> {
David Benjamin99d3c222023-06-03 23:00:40 -0400571 static void Free(Stack *sk) {
572 OPENSSL_sk_free(reinterpret_cast<OPENSSL_STACK *>(sk));
573 }
David Benjamin01219532017-07-25 22:33:06 -0400574};
575
576// Stacks defined with |DEFINE_STACK_OF| are freed with |sk_pop_free| and the
577// corresponding type's deleter.
578template <typename Stack>
David Benjamin493d5cb2022-04-18 17:20:27 -0400579struct DeleterImpl<Stack, std::enable_if_t<!StackTraits<Stack>::kIsConst>> {
David Benjamin01219532017-07-25 22:33:06 -0400580 static void Free(Stack *sk) {
David Benjaminfb4e2e02018-09-23 15:59:51 -0500581 // sk_FOO_pop_free is defined by macros and bound by name, so we cannot
582 // access it from C++ here.
583 using Type = typename StackTraits<Stack>::Type;
David Benjamin99d3c222023-06-03 23:00:40 -0400584 OPENSSL_sk_pop_free_ex(
585 reinterpret_cast<OPENSSL_STACK *>(sk),
586 [](OPENSSL_sk_free_func /* unused */, void *ptr) {
587 DeleterImpl<Type>::Free(reinterpret_cast<Type *>(ptr));
588 },
589 nullptr);
David Benjamin01219532017-07-25 22:33:06 -0400590 }
591};
592
David Benjaminec783832017-07-25 23:23:03 -0400593template <typename Stack>
594class StackIteratorImpl {
595 public:
596 using Type = typename StackTraits<Stack>::Type;
597 // Iterators must be default-constructable.
598 StackIteratorImpl() : sk_(nullptr), idx_(0) {}
599 StackIteratorImpl(const Stack *sk, size_t idx) : sk_(sk), idx_(idx) {}
600
601 bool operator==(StackIteratorImpl other) const {
602 return sk_ == other.sk_ && idx_ == other.idx_;
603 }
604 bool operator!=(StackIteratorImpl other) const {
605 return !(*this == other);
606 }
607
608 Type *operator*() const {
609 return reinterpret_cast<Type *>(
David Benjamin99d3c222023-06-03 23:00:40 -0400610 OPENSSL_sk_value(reinterpret_cast<const OPENSSL_STACK *>(sk_), idx_));
David Benjaminec783832017-07-25 23:23:03 -0400611 }
612
613 StackIteratorImpl &operator++(/* prefix */) {
614 idx_++;
615 return *this;
616 }
617
618 StackIteratorImpl operator++(int /* postfix */) {
619 StackIteratorImpl copy(*this);
620 ++(*this);
621 return copy;
622 }
623
624 private:
625 const Stack *sk_;
626 size_t idx_;
627};
628
629template <typename Stack>
David Benjamin493d5cb2022-04-18 17:20:27 -0400630using StackIterator =
631 std::enable_if_t<StackTraits<Stack>::kIsStack, StackIteratorImpl<Stack>>;
David Benjaminec783832017-07-25 23:23:03 -0400632
David Benjamin01219532017-07-25 22:33:06 -0400633} // namespace internal
634
David Benjamin6e9321f2017-07-25 23:49:58 -0400635// PushToStack pushes |elem| to |sk|. It returns true on success and false on
636// allocation failure.
637template <typename Stack>
David Benjamin493d5cb2022-04-18 17:20:27 -0400638inline std::enable_if_t<!internal::StackTraits<Stack>::kIsConst, bool>
639PushToStack(Stack *sk,
640 UniquePtr<typename internal::StackTraits<Stack>::Type> elem) {
David Benjamin99d3c222023-06-03 23:00:40 -0400641 if (!OPENSSL_sk_push(reinterpret_cast<OPENSSL_STACK *>(sk), elem.get())) {
David Benjamin6e9321f2017-07-25 23:49:58 -0400642 return false;
643 }
David Benjamin99d3c222023-06-03 23:00:40 -0400644 // OPENSSL_sk_push takes ownership on success.
David Benjamin6e9321f2017-07-25 23:49:58 -0400645 elem.release();
646 return true;
647}
648
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700649BSSL_NAMESPACE_END
David Benjamin01219532017-07-25 22:33:06 -0400650
David Benjaminec783832017-07-25 23:23:03 -0400651// Define begin() and end() for stack types so C++ range for loops work.
652template <typename Stack>
David Benjamina9436132018-09-23 18:36:01 -0500653inline bssl::internal::StackIterator<Stack> begin(const Stack *sk) {
David Benjaminec783832017-07-25 23:23:03 -0400654 return bssl::internal::StackIterator<Stack>(sk, 0);
655}
656
657template <typename Stack>
David Benjamina9436132018-09-23 18:36:01 -0500658inline bssl::internal::StackIterator<Stack> end(const Stack *sk) {
David Benjaminec783832017-07-25 23:23:03 -0400659 return bssl::internal::StackIterator<Stack>(
David Benjamin99d3c222023-06-03 23:00:40 -0400660 sk, OPENSSL_sk_num(reinterpret_cast<const OPENSSL_STACK *>(sk)));
David Benjaminec783832017-07-25 23:23:03 -0400661}
662
David Benjamin01219532017-07-25 22:33:06 -0400663} // extern C++
664#endif
665
David Benjamin4512b792017-08-18 19:21:50 -0400666#endif // OPENSSL_HEADER_STACK_H