Commit 74edd30c9f for openssl.org

commit 74edd30c9f6b3a583ca05fc97f296ddd0e161b78
Author: Nikola Pajkovsky <nikolap@openssl.org>
Date:   Tue May 12 11:32:10 2026 +0200

    stack: use free thunk when deep copy cleanup fails

    internal_copy() used the generic OPENSSL_sk_freefunc directly when a deep
    copy failed after copying some elements.  For typed stacks, callers pass
    type-specific free callbacks that have been cast to OPENSSL_sk_freefunc, so
    calling them through the generic function pointer type is undefined behavior.

    Signed-off-by: Nikola Pajkovsky <nikolap@openssl.org>

    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    Reviewed-by: Neil Horman <nhorman@openssl.org>
    MergeDate: Wed May 20 15:53:43 2026
    (Merged from https://github.com/openssl/openssl/pull/31151)

diff --git a/crypto/stack/stack.c b/crypto/stack/stack.c
index e797554783..bd3c6f54ef 100644
--- a/crypto/stack/stack.c
+++ b/crypto/stack/stack.c
@@ -47,6 +47,16 @@ OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk,
     return old;
 }

+static void free_with_thunk(OPENSSL_STACK *sk, OPENSSL_sk_freefunc free_func, const void *data)
+{
+    if (data == NULL)
+        return;
+    if (sk->free_thunk != NULL)
+        sk->free_thunk(free_func, (void *)data);
+    else
+        free_func((void *)data);
+}
+
 static OPENSSL_STACK *internal_copy(const OPENSSL_STACK *sk,
     OPENSSL_sk_copyfunc copy_func,
     OPENSSL_sk_freefunc free_func)
@@ -80,8 +90,7 @@ static OPENSSL_STACK *internal_copy(const OPENSSL_STACK *sk,
                 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]);
+                    free_with_thunk(ret, free_func, ret->data[i]);
                 goto err;
             }
         }
@@ -460,14 +469,9 @@ void OPENSSL_sk_pop_free(OPENSSL_STACK *st, OPENSSL_sk_freefunc func)
     if (st == NULL)
         return;

-    for (i = 0; i < st->num; i++) {
-        if (st->data[i] != NULL) {
-            if (st->free_thunk != NULL)
-                st->free_thunk(func, (void *)st->data[i]);
-            else
-                func((void *)st->data[i]);
-        }
-    }
+    for (i = 0; i < st->num; i++)
+        free_with_thunk(st, func, st->data[i]);
+
     OPENSSL_sk_free(st);
 }