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