1.\" $OpenBSD: OPENSSL_sk_new.3,v 1.13 2024/03/04 09:47:34 tb Exp $ 2.\" 3.\" Copyright (c) 2018 Ingo Schwarze <schwarze@openbsd.org> 4.\" 5.\" Permission to use, copy, modify, and distribute this software for any 6.\" purpose with or without fee is hereby granted, provided that the above 7.\" copyright notice and this permission notice appear in all copies. 8.\" 9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16.\" 17.Dd $Mdocdate: March 4 2024 $ 18.Dt OPENSSL_SK_NEW 3 19.Os 20.Sh NAME 21.Nm sk_new_null , 22.Nm sk_new , 23.Nm sk_set_cmp_func , 24.Nm sk_dup , 25.Nm sk_free , 26.Nm sk_pop_free , 27.Nm sk_num , 28.Nm sk_value , 29.Nm sk_find , 30.Nm sk_sort , 31.Nm sk_is_sorted , 32.Nm sk_push , 33.Nm sk_unshift , 34.Nm sk_insert , 35.Nm sk_set , 36.Nm sk_pop , 37.Nm sk_shift , 38.Nm sk_delete , 39.Nm sk_delete_ptr , 40.Nm sk_zero 41.Nd variable-sized arrays of void pointers, called OpenSSL stacks 42.Sh SYNOPSIS 43.In openssl/stack.h 44.Ft _STACK * 45.Fn sk_new_null void 46.Ft _STACK * 47.Fo sk_new 48.Fa "int (*compfunc)(const void *, const void *)" 49.Fc 50.Ft old_function_pointer 51.Fo sk_set_cmp_func 52.Fa "_STACK *stack" 53.Fa "int (*compfunc)(const void *, const void *)" 54.Fc 55.Ft _STACK * 56.Fo sk_dup 57.Fa "_STACK *stack" 58.Fc 59.Ft void 60.Fo sk_free 61.Fa "_STACK *stack" 62.Fc 63.Ft void 64.Fo sk_pop_free 65.Fa "_STACK *stack" 66.Fa "void (*freefunc)(void *)" 67.Fc 68.Ft int 69.Fo sk_num 70.Fa "const _STACK *stack" 71.Fc 72.Ft void * 73.Fo sk_value 74.Fa "const _STACK *stack" 75.Fa "int index" 76.Fc 77.Ft int 78.Fo sk_find 79.Fa "_STACK *stack" 80.Fa "void *wanted" 81.Fc 82.Ft void 83.Fo sk_sort 84.Fa "_STACK *stack" 85.Fc 86.Ft int 87.Fo sk_is_sorted 88.Fa "const _STACK *stack" 89.Fc 90.Ft int 91.Fo sk_push 92.Fa "_STACK *stack" 93.Fa "void *new_item" 94.Fc 95.Ft int 96.Fo sk_unshift 97.Fa "_STACK *stack" 98.Fa "void *new_item" 99.Fc 100.Ft int 101.Fo sk_insert 102.Fa "_STACK *stack" 103.Fa "void *new_item" 104.Fa "int index" 105.Fc 106.Ft void * 107.Fo sk_set 108.Fa "_STACK *stack" 109.Fa "int index" 110.Fa "void *new_item" 111.Fc 112.Ft void * 113.Fo sk_pop 114.Fa "_STACK *stack" 115.Fc 116.Ft void * 117.Fo sk_shift 118.Fa "_STACK *stack" 119.Fc 120.Ft void * 121.Fo sk_delete 122.Fa "_STACK *stack" 123.Fa "int index" 124.Fc 125.Ft void * 126.Fo sk_delete_ptr 127.Fa "_STACK *stack" 128.Fa "void *wanted" 129.Fc 130.Ft void 131.Fo sk_zero 132.Fa "_STACK *stack" 133.Fc 134.Sh DESCRIPTION 135OpenSSL introduced an idiosyncratic concept of variable sized arrays 136of pointers and somewhat misleadingly called such an array a 137.Dq stack . 138Intrinsically, and as documented in this manual page, OpenSSL stacks 139are not type safe but only handle 140.Vt void * 141function arguments and return values. 142.Pp 143OpenSSL also provides a fragile, unusually complicated system of 144macro-generated wrappers that offers superficial type safety at the 145expense of extensive obfuscation, implemented using large amounts 146of autogenerated code involving exceedingly ugly, nested 147.Xr cpp 1 148macros; see the 149.Xr STACK_OF 3 150manual page for details. 151.Pp 152The fundamental data type is the 153.Vt _STACK 154structure. 155It stores a variable number of void pointers 156and remembers the number of pointers currently stored. 157It can optionally hold a pointer to a comparison function. 158As long as no comparison function is installed, the order of pointers 159is meaningful; as soon as a comparison function is installed, it 160becomes ill-defined. 161.Pp 162.Fn sk_new_null 163allocates and initializes a new, empty stack. 164.Fn sk_new 165is identical except that it also installs 166.Fa compfunc 167as the comparison function for the new stack object. 168.Fn sk_set_cmp_func 169installs 170.Fa compfunc 171for the existing 172.Fa stack . 173The 174.Fa compfunc 175is allowed to be 176.Dv NULL , 177but the 178.Fa stack 179is not. 180.Pp 181.Fn sk_dup 182creates a shallow copy of the given 183.Fa stack , 184which must not be a 185.Dv NULL 186pointer. 187It neither copies the objects pointed to from the stack nor 188increases their reference counts, but merely copies the pointers. 189Extreme care must be taken in order to avoid freeing the memory twice, 190for example by calling 191.Fn sk_free 192on one copy and only calling 193.Fn sk_pop_free 194on the other. 195.Pp 196.Fn sk_free 197frees the given 198.Fa stack . 199It does not free any of the pointers stored on the stack. 200Unless these pointers are merely copies of pointers owned by 201other objects, they must be freed before calling 202.Fn sk_free , 203in order to avoid leaking memory. 204If 205.Fa stack 206is a 207.Dv NULL 208pointer, no action occurs. 209.Pp 210.Fn sk_pop_free 211is severely misnamed. 212It does not at all do what one would expect from a function called 213.Dq pop . 214Instead, it does the same as 215.Fn sk_free , 216except that it also calls the function 217.Fa freefunc 218on each of the pointers contained in the 219.Fa stack . 220If the calls to 221.Fa freefunc 222are intended to free the memory in use by the objects on the stack, 223ensure that no other pointers to the same objects remain elsewhere. 224.Pp 225.Fn sk_find 226searches the 227.Fa stack 228for the 229.Fa wanted 230pointer. 231If the 232.Fa stack 233contains more than one copy of the 234.Fa wanted 235pointer, only the first match is found. 236If a comparison function is installed for the stack, the stack is 237first sorted with 238.Fn sk_sort , 239and instead of comparing pointers, two pointers are considered to match 240if the comparison function returns 0. 241.Pp 242.Fn sk_sort 243sorts the 244.Fa stack 245using 246.Xr qsort 3 247and the installed comparison function. 248If 249.Fa stack 250is a 251.Dv NULL 252pointer or already considered sorted, no action occurs. 253This function can only be called if a comparison function is installed. 254.Pp 255.Fn sk_is_sorted 256reports whether the 257.Fa stack 258is considered sorted. 259Calling 260.Fn sk_new_null 261or 262.Fn sk_new , 263successfully calling 264.Fn sk_push , 265.Fn sk_unshift , 266.Fn sk_insert , 267or 268.Fn sk_set , 269or changing the comparison function sets the state to unsorted. 270If a comparison function is installed, calling 271.Fn sk_sort , 272or 273.Fn sk_find 274sets the state to sorted. 275.Pp 276.Fn sk_push 277pushes 278.Fa new_item 279onto the end of the 280.Fa stack , 281increasing the number of pointers by 1. 282If 283.Fa stack 284is a 285.Dv NULL 286pointer, no action occurs. 287.Pp 288.Fn sk_unshift 289inserts 290.Fa new_item 291at the beginning of the 292.Fa stack , 293such that it gets the index 0. 294The number of pointers increases by 1. 295If 296.Fa stack 297is a 298.Dv NULL 299pointer, no action occurs. 300.Pp 301.Fn sk_insert 302inserts the 303.Fa new_item 304into the 305.Fa stack 306such that it gets the given 307.Fa index . 308If 309.Fa index 310is less than 0 or greater than or equal to 311.Fn sk_num stack , 312the effect is the same as for 313.Fn sk_push . 314If 315.Fa stack 316is a 317.Dv NULL 318pointer, no action occurs. 319.Pp 320.Fn sk_set 321replaces the pointer with the given 322.Fa index 323on the 324.Fa stack 325with the 326.Fa new_item . 327The old pointer is not freed, 328which may leak memory if no copy of it exists elsewhere. 329If 330.Fa stack 331is a 332.Dv NULL 333pointer or if 334.Fa index 335is less than 0 or greater than or equal to 336.Fn sk_num stack , 337no action occurs. 338.Pp 339.Fn sk_pop 340and 341.Fn sk_shift 342remove the pointer with the highest or lowest index from the 343.Fa stack , 344respectively, reducing the number of pointers by 1. 345If 346.Fa stack 347is a 348.Dv NULL 349pointer or if it is empty, no action occurs. 350.Pp 351.Fn sk_delete 352removes the pointer with the given 353.Fa index 354from the 355.Fa stack , 356reducing the number of pointers by 1. 357If 358.Fa stack 359is a 360.Dv NULL 361pointer or the 362.Fa index 363is less than 0 or greater than or equal to 364.Fn sk_num stack , 365no action occurs. 366.Pp 367.Fn sk_delete_ptr 368removes the 369.Fa wanted 370pointer from the 371.Fa stack , 372reducing the number of pointers by 1 if it is found. 373It never uses a comparison function 374but only compares pointers themselves. 375The 376.Fa stack 377pointer must not be 378.Dv NULL . 379.Pp 380.Fn sk_zero 381removes all pointers from the 382.Fa stack . 383It does not free any of the pointers. 384Unless these pointers are merely copies of pointers owned by other 385objects, they must be freed before calling 386.Fn sk_zero , 387in order to avoid leaking memory. 388If 389.Fa stack 390is a 391.Dv NULL 392pointer, no action occurs. 393.Sh RETURN VALUES 394.Fn sk_new_null , 395.Fn sk_new , 396and 397.Fn sk_dup 398return a pointer to the newly allocated stack object or 399.Dv NULL 400if insufficient memory is available. 401.Pp 402.Fn sk_set_cmp_func 403returns a pointer to the comparison function 404that was previously installed for the 405.Fa stack 406or 407.Dv NULL 408if none was installed. 409.Pp 410.Fn sk_num 411returns the number of pointers currently stored on the 412.Fa stack , 413or \-1 if 414.Fa stack 415is a 416.Dv NULL 417pointer. 418.Pp 419.Fn sk_value 420returns the pointer with the given 421.Fa index 422from the 423.Fa stack , 424or 425.Dv NULL 426if 427.Fa stack 428is a 429.Dv NULL 430pointer or if the 431.Fa index 432is less than 0 or greater than or equal to 433.Fn sk_num stack . 434.Pp 435.Fn sk_find 436returns the lowest index considered to match or \-1 if 437.Fa stack 438is a 439.Dv NULL 440pointer or if no match is found. 441.Pp 442.Fn sk_is_sorted 443returns 1 if the 444.Fa stack 445is considered sorted or if it is a 446.Dv NULL 447pointer, or 0 otherwise. 448.Pp 449.Fn sk_push , 450.Fn sk_unshift , 451and 452.Fn sk_insert 453return the new number of pointers on the 454.Fa stack 455or 0 if 456.Fa stack 457is a 458.Dv NULL 459pointer or if memory allocation fails. 460.Pp 461.Fn sk_set 462returns 463.Fa new_item 464or 465.Dv NULL 466if 467.Fa stack 468is a 469.Dv NULL 470pointer or if the 471.Fa index 472is less than 0 or greater than or equal to 473.Fn sk_num stack . 474.Pp 475.Fn sk_pop 476and 477.Fn sk_shift 478return the deleted pointer or 479.Dv NULL 480if 481.Fa stack 482is a 483.Dv NULL 484pointer or if it is empty. 485.Pp 486.Fn sk_delete 487returns the deleted pointer or 488.Dv NULL 489if 490.Fa stack 491is a 492.Dv NULL 493pointer or if the 494.Fa index 495is less than 0 or greater than or equal to 496.Fn sk_num stack . 497.Pp 498.Fn sk_delete_ptr 499returns 500.Fa wanted 501or 502.Dv NULL 503if it is not found. 504.Sh SEE ALSO 505.Xr STACK_OF 3 506.Sh HISTORY 507.Fn sk_new_null , 508.Fn sk_new , 509.Fn sk_free , 510.Fn sk_pop_free , 511.Fn sk_num , 512.Fn sk_value , 513.Fn sk_find , 514.Fn sk_push , 515.Fn sk_unshift , 516.Fn sk_insert , 517.Fn sk_pop , 518.Fn sk_shift , 519.Fn sk_delete , 520and 521.Fn sk_delete_ptr 522first appeared in SSLeay 0.5.1. 523.Fn sk_set_cmp_func , 524.Fn sk_dup , 525and 526.Fn sk_zero 527first appeared in SSLeay 0.8.0. 528These functions have been available since 529.Ox 2.4 . 530.Pp 531.Fn sk_set 532first appeared in OpenSSL 0.9.3. 533.Fn sk_sort 534first appeared in OpenSSL 0.9.4. 535Both functions have been available since 536.Ox 2.6 . 537.Pp 538.Fn sk_is_sorted 539first appeared in OpenSSL 0.9.7e and has been available since 540.Ox 3.8 . 541.Sh BUGS 542Even if a comparison function is installed, empty stacks and 543stacks containing a single pointer are sometimes considered 544sorted and sometimes considered unsorted. 545.Pp 546If a comparison function is installed, the concept of 547.Dq first match 548in 549.Fn sk_find 550is ill-defined because 551.Xr qsort 3 552is not a stable sorting function. 553It is probably best to only assume that they return an arbitrary match. 554