jsing will make _STACK opaque. Only two things notice: rust-openssl (already fixed upstream) and M2Crypto.
M2Crypto contains two compat shims for STACK_OF(). sk_free() has been available since forever so I don't really understand why that was ever needed, but it's easy to fix. I made deep_copy() always fail. I doubt it is needed for anything (although I would be happy to learn how to know for sure). Also, sk_TYPE_deep_copy() requires TYPE_dup() and TYPE_free() with usual signatures, they are then cast to a "generic" OPENSSL_sk_{copy,free}func before they're called. My understanding is that that's undefined because void * and TYPE * have different alignment requirements. Regress tests look the same with or without this patch. Index: Makefile =================================================================== RCS file: /cvs/ports/security/py-M2Crypto/Makefile,v diff -u -p -r1.41 Makefile --- Makefile 20 Dec 2023 13:10:10 -0000 1.41 +++ Makefile 22 Jan 2024 17:15:28 -0000 @@ -3,6 +3,7 @@ COMMENT = crypto and TLS toolkit for Py MODPY_EGG_VERSION = 0.40.1 DISTNAME = M2Crypto-${MODPY_EGG_VERSION} PKGNAME = py-${DISTNAME} +REVISION = 0 CATEGORIES = security Index: patches/patch-src_SWIG__lib_i =================================================================== RCS file: /cvs/ports/security/py-M2Crypto/patches/patch-src_SWIG__lib_i,v diff -u -p -r1.3 patch-src_SWIG__lib_i --- patches/patch-src_SWIG__lib_i 11 Mar 2022 19:53:53 -0000 1.3 +++ patches/patch-src_SWIG__lib_i 22 Jan 2024 15:32:50 -0000 @@ -12,3 +12,54 @@ Index: src/SWIG/_lib.i typedef void (*OPENSSL_sk_freefunc)(void *); typedef void *(*OPENSSL_sk_copyfunc)(const void *); typedef struct stack_st OPENSSL_STACK; +@@ -31,47 +31,15 @@ typedef struct stack_st OPENSSL_STACK; + + void OPENSSL_sk_free(OPENSSL_STACK *st) + { +- if (st == NULL) +- return; +- OPENSSL_free(st->data); +- OPENSSL_free(st); ++ sk_free(st); + } + + OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk, + OPENSSL_sk_copyfunc copy_func, + OPENSSL_sk_freefunc free_func) + { +- OPENSSL_STACK *ret; +- int i; +- +- if (sk->num < 0) +- return NULL; +- +- if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) +- return NULL; +- +- /* direct structure assignment */ +- *ret = *sk; +- +- ret->num_alloc = sk->num > MIN_NODES ? (size_t)sk->num : MIN_NODES; +- ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc); +- if (ret->data == NULL) { +- OPENSSL_free(ret); +- return NULL; +- } +- +- for (i = 0; i < ret->num; ++i) { +- if (sk->data[i] == NULL) +- continue; +- if ((ret->data[i] = copy_func(sk->data[i])) == NULL) { +- while (--i >= 0) +- if (ret->data[i] != NULL) +- free_func((void *)ret->data[i]); +- OPENSSL_sk_free(ret); +- return NULL; +- } +- } +- return ret; ++ /* Do not support this. It relieas on UB via function pointer casting. */ ++ return NULL; + } + #endif /* OpenSSL 1.0.2 copmatbility shim */ +