]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
stack: use free thunk when deep copy cleanup fails
authorNikola Pajkovsky <nikolap@openssl.org>
Tue, 12 May 2026 09:32:10 +0000 (11:32 +0200)
committerNeil Horman <nhorman@openssl.org>
Wed, 20 May 2026 15:53:32 +0000 (11:53 -0400)
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)

crypto/stack/stack.c

index e797554783f84a90fb12125b0b06344b61923f3d..bd3c6f54ef1107e0c71c747426910ac63a7cea9e 100644 (file)
@@ -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);
 }