• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* 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 
62 #if defined(__cplusplus)
63 extern "C" {
64 #endif
65 
66 
67 // A stack, in OpenSSL, is an array of pointers. They are the most commonly
68 // used collection object.
69 //
70 // 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|.
73 //
74 // The |DECLARE_STACK_OF| macro makes |STACK_OF(FOO)| available, and
75 // |DEFINE_STACK_OF| makes the corresponding functions available.
76 
77 
78 // 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.
119 typedef 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.
123 typedef SAMPLE *(*sk_SAMPLE_copy_func)(const 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 typedef int (*sk_SAMPLE_cmp_func)(const SAMPLE *const *a,
131                                   const SAMPLE *const *b);
132 
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.
135 STACK_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.
139 STACK_OF(SAMPLE) *sk_SAMPLE_new_null(void);
140 
141 // sk_SAMPLE_num returns the number of elements in |sk|.
142 size_t sk_SAMPLE_num(const STACK_OF(SAMPLE) *sk);
143 
144 // sk_SAMPLE_zero resets |sk| to the empty state but does nothing to free the
145 // individual elements themselves.
146 void sk_SAMPLE_zero(STACK_OF(SAMPLE) *sk);
147 
148 // sk_SAMPLE_value returns the |i|th pointer in |sk|, or NULL if |i| is out of
149 // range.
150 SAMPLE *sk_SAMPLE_value(const STACK_OF(SAMPLE) *sk, size_t i);
151 
152 // sk_SAMPLE_set sets the |i|th pointer in |sk| to |p| and returns |p|. If |i|
153 // is out of range, it returns NULL.
154 SAMPLE *sk_SAMPLE_set(STACK_OF(SAMPLE) *sk, size_t i, SAMPLE *p);
155 
156 // sk_SAMPLE_free frees |sk|, but does nothing to free the individual elements.
157 // Use |sk_SAMPLE_pop_free| to also free the elements.
158 void sk_SAMPLE_free(STACK_OF(SAMPLE) *sk);
159 
160 // sk_SAMPLE_pop_free calls |free_func| on each element in |sk| and then
161 // frees the stack itself.
162 void sk_SAMPLE_pop_free(STACK_OF(SAMPLE) *sk, sk_SAMPLE_free_func free_func);
163 
164 // sk_SAMPLE_insert inserts |p| into the stack at index |where|, moving existing
165 // elements if needed. It returns the length of the new stack, or zero on
166 // error.
167 size_t sk_SAMPLE_insert(STACK_OF(SAMPLE) *sk, SAMPLE *p, size_t where);
168 
169 // sk_SAMPLE_delete removes the pointer at index |where|, moving other elements
170 // down if needed. It returns the removed pointer, or NULL if |where| is out of
171 // range.
172 SAMPLE *sk_SAMPLE_delete(STACK_OF(SAMPLE) *sk, size_t where);
173 
174 // sk_SAMPLE_delete_ptr removes, at most, one instance of |p| from |sk| based on
175 // pointer equality. If an instance of |p| is found then |p| is returned,
176 // otherwise it returns NULL.
177 SAMPLE *sk_SAMPLE_delete_ptr(STACK_OF(SAMPLE) *sk, const SAMPLE *p);
178 
179 // sk_SAMPLE_delete_if_func is the callback function for |sk_SAMPLE_delete_if|.
180 // It should return one to remove |p| and zero to keep it.
181 typedef int (*sk_SAMPLE_delete_if_func)(SAMPLE *p, void *data);
182 
183 // sk_SAMPLE_delete_if calls |func| with each element of |sk| and removes the
184 // entries where |func| returned one. This function does not free or return
185 // removed pointers so, if |sk| owns its contents, |func| should release the
186 // pointers prior to returning one.
187 void sk_SAMPLE_delete_if(STACK_OF(SAMPLE) *sk, sk_SAMPLE_delete_if_func func,
188                          void *data);
189 
190 // sk_SAMPLE_find find the first value in |sk| equal to |p|. |sk|'s comparison
191 // function determines equality, or pointer equality if |sk| has no comparison
192 // function.
193 //
194 // If the stack is sorted (see |sk_SAMPLE_sort|), this function uses a binary
195 // search. Otherwise it performs a linear search. If it finds a matching
196 // element, it writes the index to |*out_index| (if |out_index| is not NULL) and
197 // returns one. Otherwise, it returns zero.
198 //
199 // Note this differs from OpenSSL. The type signature is slightly different, and
200 // OpenSSL's version will implicitly sort |sk| if it has a comparison function
201 // defined.
202 int sk_SAMPLE_find(const STACK_OF(SAMPLE) *sk, size_t *out_index,
203                    const SAMPLE *p);
204 
205 // sk_SAMPLE_shift removes and returns the first element in |sk|, or NULL if
206 // |sk| is empty.
207 SAMPLE *sk_SAMPLE_shift(STACK_OF(SAMPLE) *sk);
208 
209 // sk_SAMPLE_push appends |p| to |sk| and returns the length of the new stack,
210 // or 0 on allocation failure.
211 size_t sk_SAMPLE_push(STACK_OF(SAMPLE) *sk, SAMPLE *p);
212 
213 // sk_SAMPLE_pop removes and returns the last element of |sk|, or NULL if |sk|
214 // is empty.
215 SAMPLE *sk_SAMPLE_pop(STACK_OF(SAMPLE) *sk);
216 
217 // sk_SAMPLE_dup performs a shallow copy of a stack and returns the new stack,
218 // or NULL on error. Use |sk_SAMPLE_deep_copy| to also copy the elements.
219 STACK_OF(SAMPLE) *sk_SAMPLE_dup(const STACK_OF(SAMPLE) *sk);
220 
221 // sk_SAMPLE_sort sorts the elements of |sk| into ascending order based on the
222 // comparison function. The stack maintains a "sorted" flag and sorting an
223 // already sorted stack is a no-op.
224 void sk_SAMPLE_sort(STACK_OF(SAMPLE) *sk);
225 
226 // sk_SAMPLE_is_sorted returns one if |sk| is known to be sorted and zero
227 // otherwise.
228 int sk_SAMPLE_is_sorted(const STACK_OF(SAMPLE) *sk);
229 
230 // sk_SAMPLE_set_cmp_func sets the comparison function to be used by |sk| and
231 // returns the previous one.
232 sk_SAMPLE_cmp_func sk_SAMPLE_set_cmp_func(STACK_OF(SAMPLE) *sk,
233                                           sk_SAMPLE_cmp_func comp);
234 
235 // sk_SAMPLE_deep_copy performs a copy of |sk| and of each of the non-NULL
236 // elements in |sk| by using |copy_func|. If an error occurs, it calls
237 // |free_func| to free any copies already made and returns NULL.
238 STACK_OF(SAMPLE) *sk_SAMPLE_deep_copy(const STACK_OF(SAMPLE) *sk,
239                                       sk_SAMPLE_copy_func copy_func,
240                                       sk_SAMPLE_free_func free_func);
241 
242 #endif  // Sample
243 
244 
245 // Private functions.
246 //
247 // TODO(https://crbug.com/boringssl/499): Rename to |OPENSSL_sk_foo|, after
248 // external code that calls them is fixed.
249 
250 // OPENSSL_sk_free_func is a function that frees an element in a stack. Note its
251 // actual type is void (*)(T *) for some T. Low-level |sk_*| functions will be
252 // passed a type-specific wrapper to call it correctly.
253 typedef void (*OPENSSL_sk_free_func)(void *ptr);
254 
255 // OPENSSL_sk_copy_func is a function that copies an element in a stack. Note
256 // its actual type is T *(*)(const T *) for some T. Low-level |sk_*| functions
257 // will be passed a type-specific wrapper to call it correctly.
258 typedef void *(*OPENSSL_sk_copy_func)(const void *ptr);
259 
260 // OPENSSL_sk_cmp_func is a comparison function that returns a value < 0, 0 or >
261 // 0 if |*a| is less than, equal to or greater than |*b|, respectively.  Note
262 // the extra indirection - the function is given a pointer to a pointer to the
263 // element. This differs from the usual qsort/bsearch comparison function.
264 //
265 // Note its actual type is |int (*)(const T *const *a, const T *const *b)|.
266 // Low-level |sk_*| functions will be passed a type-specific wrapper to call it
267 // correctly.
268 typedef int (*OPENSSL_sk_cmp_func)(const void *const *a, const void *const *b);
269 
270 // OPENSSL_sk_delete_if_func is the generic version of
271 // |sk_SAMPLE_delete_if_func|.
272 typedef int (*OPENSSL_sk_delete_if_func)(void *obj, void *data);
273 
274 // The following function types call the above type-erased signatures with the
275 // true types.
276 typedef void (*OPENSSL_sk_call_free_func)(OPENSSL_sk_free_func, void *);
277 typedef void *(*OPENSSL_sk_call_copy_func)(OPENSSL_sk_copy_func, const void *);
278 typedef int (*OPENSSL_sk_call_cmp_func)(OPENSSL_sk_cmp_func,
279                                         const void *const *,
280                                         const void *const *);
281 typedef int (*OPENSSL_sk_call_delete_if_func)(OPENSSL_sk_delete_if_func, void *,
282                                               void *);
283 
284 // stack_st contains an array of pointers. It is not designed to be used
285 // directly, rather the wrapper macros should be used.
286 typedef struct stack_st {
287   // num contains the number of valid pointers in |data|.
288   size_t num;
289   void **data;
290   // sorted is non-zero if the values pointed to by |data| are in ascending
291   // order, based on |comp|.
292   int sorted;
293   // num_alloc contains the number of pointers allocated in the buffer pointed
294   // to by |data|, which may be larger than |num|.
295   size_t num_alloc;
296   // comp is an optional comparison function.
297   OPENSSL_sk_cmp_func comp;
298 } _STACK;
299 
300 // The following are raw stack functions. They implement the corresponding typed
301 // |sk_SAMPLE_*| functions generated by |DEFINE_STACK_OF|. Callers shouldn't be
302 // using them. Rather, callers should use the typed functions.
303 OPENSSL_EXPORT _STACK *sk_new(OPENSSL_sk_cmp_func comp);
304 OPENSSL_EXPORT _STACK *sk_new_null(void);
305 OPENSSL_EXPORT size_t sk_num(const _STACK *sk);
306 OPENSSL_EXPORT void sk_zero(_STACK *sk);
307 OPENSSL_EXPORT void *sk_value(const _STACK *sk, size_t i);
308 OPENSSL_EXPORT void *sk_set(_STACK *sk, size_t i, void *p);
309 OPENSSL_EXPORT void sk_free(_STACK *sk);
310 OPENSSL_EXPORT void sk_pop_free_ex(_STACK *sk,
311                                    OPENSSL_sk_call_free_func call_free_func,
312                                    OPENSSL_sk_free_func free_func);
313 OPENSSL_EXPORT size_t sk_insert(_STACK *sk, void *p, size_t where);
314 OPENSSL_EXPORT void *sk_delete(_STACK *sk, size_t where);
315 OPENSSL_EXPORT void *sk_delete_ptr(_STACK *sk, const void *p);
316 OPENSSL_EXPORT void sk_delete_if(_STACK *sk,
317                                  OPENSSL_sk_call_delete_if_func call_func,
318                                  OPENSSL_sk_delete_if_func func, void *data);
319 OPENSSL_EXPORT int sk_find(const _STACK *sk, size_t *out_index, const void *p,
320                            OPENSSL_sk_call_cmp_func call_cmp_func);
321 OPENSSL_EXPORT void *sk_shift(_STACK *sk);
322 OPENSSL_EXPORT size_t sk_push(_STACK *sk, void *p);
323 OPENSSL_EXPORT void *sk_pop(_STACK *sk);
324 OPENSSL_EXPORT _STACK *sk_dup(const _STACK *sk);
325 OPENSSL_EXPORT void sk_sort(_STACK *sk, OPENSSL_sk_call_cmp_func call_cmp_func);
326 OPENSSL_EXPORT int sk_is_sorted(const _STACK *sk);
327 OPENSSL_EXPORT OPENSSL_sk_cmp_func sk_set_cmp_func(_STACK *sk,
328                                                    OPENSSL_sk_cmp_func comp);
329 OPENSSL_EXPORT _STACK *sk_deep_copy(const _STACK *sk,
330                                     OPENSSL_sk_call_copy_func call_copy_func,
331                                     OPENSSL_sk_copy_func copy_func,
332                                     OPENSSL_sk_call_free_func call_free_func,
333                                     OPENSSL_sk_free_func free_func);
334 
335 // sk_pop_free behaves like |sk_pop_free_ex| but performs an invalid function
336 // pointer cast. It exists because some existing callers called |sk_pop_free|
337 // directly.
338 //
339 // TODO(davidben): Migrate callers to bssl::UniquePtr and remove this.
340 OPENSSL_EXPORT void sk_pop_free(_STACK *sk, OPENSSL_sk_free_func free_func);
341 
342 #if !defined(BORINGSSL_NO_CXX)
343 extern "C++" {
344 BSSL_NAMESPACE_BEGIN
345 namespace internal {
346 template <typename T>
347 struct StackTraits {};
348 }
349 BSSL_NAMESPACE_END
350 }
351 
352 #define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) \
353   extern "C++" {                                            \
354   BSSL_NAMESPACE_BEGIN                                      \
355   namespace internal {                                      \
356   template <>                                               \
357   struct StackTraits<STACK_OF(name)> {                      \
358     static constexpr bool kIsStack = true;                  \
359     using Type = type;                                      \
360     static constexpr bool kIsConst = is_const;              \
361   };                                                        \
362   }                                                         \
363   BSSL_NAMESPACE_END                                        \
364   }
365 
366 #else
367 #define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const)
368 #endif
369 
370 #define BORINGSSL_DEFINE_STACK_OF_IMPL(name, ptrtype, constptrtype)           \
371   /* We disable MSVC C4191 in this macro, which warns when pointers are cast  \
372    * to the wrong type. While the cast itself is valid, it is often a bug     \
373    * because calling it through the cast is UB. However, we never actually    \
374    * call functions as |OPENSSL_sk_cmp_func|. The type is just a type-erased  \
375    * function pointer. (C does not guarantee function pointers fit in         \
376    * |void*|, and GCC will warn on this.) Thus we just disable the false      \
377    * positive warning. */                                                     \
378   OPENSSL_MSVC_PRAGMA(warning(push))                                          \
379   OPENSSL_MSVC_PRAGMA(warning(disable : 4191))                                \
380                                                                               \
381   DECLARE_STACK_OF(name)                                                      \
382                                                                               \
383   typedef void (*sk_##name##_free_func)(ptrtype);                             \
384   typedef ptrtype (*sk_##name##_copy_func)(constptrtype);                     \
385   typedef int (*sk_##name##_cmp_func)(constptrtype const *,                   \
386                                       constptrtype const *);                  \
387   typedef int (*sk_##name##_delete_if_func)(ptrtype, void *);                 \
388                                                                               \
389   OPENSSL_INLINE void sk_##name##_call_free_func(                             \
390       OPENSSL_sk_free_func free_func, void *ptr) {                            \
391     ((sk_##name##_free_func)free_func)((ptrtype)ptr);                         \
392   }                                                                           \
393                                                                               \
394   OPENSSL_INLINE void *sk_##name##_call_copy_func(                            \
395       OPENSSL_sk_copy_func copy_func, const void *ptr) {                      \
396     return (void *)((sk_##name##_copy_func)copy_func)((constptrtype)ptr);     \
397   }                                                                           \
398                                                                               \
399   OPENSSL_INLINE int sk_##name##_call_cmp_func(OPENSSL_sk_cmp_func cmp_func,  \
400                                                const void *const *a,          \
401                                                const void *const *b) {        \
402     /* The data is actually stored as |void*| pointers, so read the pointer   \
403      * as |void*| and then pass the corrected type into the caller-supplied   \
404      * function, which expects |constptrtype*|. */                            \
405     constptrtype a_ptr = (constptrtype)*a;                                    \
406     constptrtype b_ptr = (constptrtype)*b;                                    \
407     return ((sk_##name##_cmp_func)cmp_func)(&a_ptr, &b_ptr);                  \
408   }                                                                           \
409                                                                               \
410   OPENSSL_INLINE int sk_##name##_call_delete_if_func(                         \
411       OPENSSL_sk_delete_if_func func, void *obj, void *data) {                \
412     return ((sk_##name##_delete_if_func)func)((ptrtype)obj, data);            \
413   }                                                                           \
414                                                                               \
415   OPENSSL_INLINE STACK_OF(name) *sk_##name##_new(sk_##name##_cmp_func comp) { \
416     return (STACK_OF(name) *)sk_new((OPENSSL_sk_cmp_func)comp);               \
417   }                                                                           \
418                                                                               \
419   OPENSSL_INLINE STACK_OF(name) *sk_##name##_new_null(void) {                 \
420     return (STACK_OF(name) *)sk_new_null();                                   \
421   }                                                                           \
422                                                                               \
423   OPENSSL_INLINE size_t sk_##name##_num(const STACK_OF(name) *sk) {           \
424     return sk_num((const _STACK *)sk);                                        \
425   }                                                                           \
426                                                                               \
427   OPENSSL_INLINE void sk_##name##_zero(STACK_OF(name) *sk) {                  \
428     sk_zero((_STACK *)sk);                                                    \
429   }                                                                           \
430                                                                               \
431   OPENSSL_INLINE ptrtype sk_##name##_value(const STACK_OF(name) *sk,          \
432                                            size_t i) {                        \
433     return (ptrtype)sk_value((const _STACK *)sk, i);                          \
434   }                                                                           \
435                                                                               \
436   OPENSSL_INLINE ptrtype sk_##name##_set(STACK_OF(name) *sk, size_t i,        \
437                                          ptrtype p) {                         \
438     return (ptrtype)sk_set((_STACK *)sk, i, (void *)p);                       \
439   }                                                                           \
440                                                                               \
441   OPENSSL_INLINE void sk_##name##_free(STACK_OF(name) *sk) {                  \
442     sk_free((_STACK *)sk);                                                    \
443   }                                                                           \
444                                                                               \
445   OPENSSL_INLINE void sk_##name##_pop_free(STACK_OF(name) *sk,                \
446                                            sk_##name##_free_func free_func) { \
447     sk_pop_free_ex((_STACK *)sk, sk_##name##_call_free_func,                  \
448                    (OPENSSL_sk_free_func)free_func);                          \
449   }                                                                           \
450                                                                               \
451   OPENSSL_INLINE size_t sk_##name##_insert(STACK_OF(name) *sk, ptrtype p,     \
452                                            size_t where) {                    \
453     return sk_insert((_STACK *)sk, (void *)p, where);                         \
454   }                                                                           \
455                                                                               \
456   OPENSSL_INLINE ptrtype sk_##name##_delete(STACK_OF(name) *sk,               \
457                                             size_t where) {                   \
458     return (ptrtype)sk_delete((_STACK *)sk, where);                           \
459   }                                                                           \
460                                                                               \
461   OPENSSL_INLINE ptrtype sk_##name##_delete_ptr(STACK_OF(name) *sk,           \
462                                                 constptrtype p) {             \
463     return (ptrtype)sk_delete_ptr((_STACK *)sk, (const void *)p);             \
464   }                                                                           \
465                                                                               \
466   OPENSSL_INLINE void sk_##name##_delete_if(                                  \
467       STACK_OF(name) *sk, sk_##name##_delete_if_func func, void *data) {      \
468     sk_delete_if((_STACK *)sk, sk_##name##_call_delete_if_func,               \
469                  (OPENSSL_sk_delete_if_func)func, data);                      \
470   }                                                                           \
471                                                                               \
472   OPENSSL_INLINE int sk_##name##_find(const STACK_OF(name) *sk,               \
473                                       size_t *out_index, constptrtype p) {    \
474     return sk_find((const _STACK *)sk, out_index, (const void *)p,            \
475                    sk_##name##_call_cmp_func);                                \
476   }                                                                           \
477                                                                               \
478   OPENSSL_INLINE ptrtype sk_##name##_shift(STACK_OF(name) *sk) {              \
479     return (ptrtype)sk_shift((_STACK *)sk);                                   \
480   }                                                                           \
481                                                                               \
482   OPENSSL_INLINE size_t sk_##name##_push(STACK_OF(name) *sk, ptrtype p) {     \
483     return sk_push((_STACK *)sk, (void *)p);                                  \
484   }                                                                           \
485                                                                               \
486   OPENSSL_INLINE ptrtype sk_##name##_pop(STACK_OF(name) *sk) {                \
487     return (ptrtype)sk_pop((_STACK *)sk);                                     \
488   }                                                                           \
489                                                                               \
490   OPENSSL_INLINE STACK_OF(name) *sk_##name##_dup(const STACK_OF(name) *sk) {  \
491     return (STACK_OF(name) *)sk_dup((const _STACK *)sk);                      \
492   }                                                                           \
493                                                                               \
494   OPENSSL_INLINE void sk_##name##_sort(STACK_OF(name) *sk) {                  \
495     sk_sort((_STACK *)sk, sk_##name##_call_cmp_func);                         \
496   }                                                                           \
497                                                                               \
498   OPENSSL_INLINE int sk_##name##_is_sorted(const STACK_OF(name) *sk) {        \
499     return sk_is_sorted((const _STACK *)sk);                                  \
500   }                                                                           \
501                                                                               \
502   OPENSSL_INLINE sk_##name##_cmp_func sk_##name##_set_cmp_func(               \
503       STACK_OF(name) *sk, sk_##name##_cmp_func comp) {                        \
504     return (sk_##name##_cmp_func)sk_set_cmp_func((_STACK *)sk,                \
505                                                  (OPENSSL_sk_cmp_func)comp);  \
506   }                                                                           \
507                                                                               \
508   OPENSSL_INLINE STACK_OF(name) *sk_##name##_deep_copy(                       \
509       const STACK_OF(name) *sk, sk_##name##_copy_func copy_func,              \
510       sk_##name##_free_func free_func) {                                      \
511     return (STACK_OF(name) *)sk_deep_copy(                                    \
512         (const _STACK *)sk, sk_##name##_call_copy_func,                       \
513         (OPENSSL_sk_copy_func)copy_func, sk_##name##_call_free_func,          \
514         (OPENSSL_sk_free_func)free_func);                                     \
515   }                                                                           \
516                                                                               \
517   OPENSSL_MSVC_PRAGMA(warning(pop))
518 
519 
520 // Built-in stacks.
521 
522 typedef char *OPENSSL_STRING;
523 
524 DEFINE_STACK_OF(void)
525 DEFINE_NAMED_STACK_OF(OPENSSL_STRING, char)
526 
527 
528 #if defined(__cplusplus)
529 }  // extern C
530 #endif
531 
532 #if !defined(BORINGSSL_NO_CXX)
533 extern "C++" {
534 
535 #include <type_traits>
536 
537 BSSL_NAMESPACE_BEGIN
538 
539 namespace internal {
540 
541 // Stacks defined with |DEFINE_CONST_STACK_OF| are freed with |sk_free|.
542 template <typename Stack>
543 struct DeleterImpl<Stack, std::enable_if_t<StackTraits<Stack>::kIsConst>> {
544   static void Free(Stack *sk) { sk_free(reinterpret_cast<_STACK *>(sk)); }
545 };
546 
547 // Stacks defined with |DEFINE_STACK_OF| are freed with |sk_pop_free| and the
548 // corresponding type's deleter.
549 template <typename Stack>
550 struct DeleterImpl<Stack, std::enable_if_t<!StackTraits<Stack>::kIsConst>> {
551   static void Free(Stack *sk) {
552     // sk_FOO_pop_free is defined by macros and bound by name, so we cannot
553     // access it from C++ here.
554     using Type = typename StackTraits<Stack>::Type;
555     sk_pop_free_ex(reinterpret_cast<_STACK *>(sk),
556                    [](OPENSSL_sk_free_func /* unused */, void *ptr) {
557                      DeleterImpl<Type>::Free(reinterpret_cast<Type *>(ptr));
558                    },
559                    nullptr);
560   }
561 };
562 
563 template <typename Stack>
564 class StackIteratorImpl {
565  public:
566   using Type = typename StackTraits<Stack>::Type;
567   // Iterators must be default-constructable.
568   StackIteratorImpl() : sk_(nullptr), idx_(0) {}
569   StackIteratorImpl(const Stack *sk, size_t idx) : sk_(sk), idx_(idx) {}
570 
571   bool operator==(StackIteratorImpl other) const {
572     return sk_ == other.sk_ && idx_ == other.idx_;
573   }
574   bool operator!=(StackIteratorImpl other) const {
575     return !(*this == other);
576   }
577 
578   Type *operator*() const {
579     return reinterpret_cast<Type *>(
580         sk_value(reinterpret_cast<const _STACK *>(sk_), idx_));
581   }
582 
583   StackIteratorImpl &operator++(/* prefix */) {
584     idx_++;
585     return *this;
586   }
587 
588   StackIteratorImpl operator++(int /* postfix */) {
589     StackIteratorImpl copy(*this);
590     ++(*this);
591     return copy;
592   }
593 
594  private:
595   const Stack *sk_;
596   size_t idx_;
597 };
598 
599 template <typename Stack>
600 using StackIterator =
601     std::enable_if_t<StackTraits<Stack>::kIsStack, StackIteratorImpl<Stack>>;
602 
603 }  // namespace internal
604 
605 // PushToStack pushes |elem| to |sk|. It returns true on success and false on
606 // allocation failure.
607 template <typename Stack>
608 inline std::enable_if_t<!internal::StackTraits<Stack>::kIsConst, bool>
609 PushToStack(Stack *sk,
610             UniquePtr<typename internal::StackTraits<Stack>::Type> elem) {
611   if (!sk_push(reinterpret_cast<_STACK *>(sk), elem.get())) {
612     return false;
613   }
614   // sk_push takes ownership on success.
615   elem.release();
616   return true;
617 }
618 
619 BSSL_NAMESPACE_END
620 
621 // Define begin() and end() for stack types so C++ range for loops work.
622 template <typename Stack>
623 inline bssl::internal::StackIterator<Stack> begin(const Stack *sk) {
624   return bssl::internal::StackIterator<Stack>(sk, 0);
625 }
626 
627 template <typename Stack>
628 inline bssl::internal::StackIterator<Stack> end(const Stack *sk) {
629   return bssl::internal::StackIterator<Stack>(
630       sk, sk_num(reinterpret_cast<const _STACK *>(sk)));
631 }
632 
633 }  // extern C++
634 #endif
635 
636 #endif  // OPENSSL_HEADER_STACK_H
637