Commit 39f46844c6 for openssl.org

commit 39f46844c6e06e26bea34f300c7fc61c06bb20b8
Author: Nikola Pajkovsky <nikolap@openssl.org>
Date:   Tue Jun 16 12:58:45 2026 +0200

    asn1: centralize aux const-callback dispatch to avoid function pointer cast

    Replace the per-call-site `(ASN1_aux_const_cb *)aux->asn1_cb` cast in
    ASN1_item_ex_i2d() and asn1_item_print_ctx() with a shared helper,
    ossl_asn1_aux_const_cb(), which invokes the legacy non-const callback
    through its real type. This avoids the UBSAN function-pointer-type
    mismatch while preserving backward compatibility.

    Fixes: https://github.com/openssl/project/issues/1970
    Signed-off-by: Nikola Pajkovsky <nikolap@openssl.org>

    Reviewed-by: Bob Beck <beck@openssl.org>
    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    Reviewed-by: Neil Horman <nhorman@openssl.org>
    MergeDate: Sun Jun 21 23:38:12 2026
    (Merged from https://github.com/openssl/openssl/pull/31541)

diff --git a/crypto/asn1/asn1_local.h b/crypto/asn1/asn1_local.h
index 46d7aca7a2..0fd1d0a842 100644
--- a/crypto/asn1/asn1_local.h
+++ b/crypto/asn1/asn1_local.h
@@ -12,6 +12,7 @@
 #if !defined(OSSL_LIBCRYPTO_ASN1_ASN1_LOCAL_H)
 #define OSSL_LIBCRYPTO_ASN1_ASN1_LOCAL_H

+#include <openssl/asn1t.h>
 #include "crypto/asn1.h"

 typedef const ASN1_VALUE const_ASN1_VALUE;
@@ -99,5 +100,7 @@ int ossl_asn1_item_ex_new_intern(ASN1_VALUE **pval, const ASN1_ITEM *it,
     OSSL_LIB_CTX *libctx, const char *propq);
 int ossl_asn1_time_time_t_to_tm(const time_t *time, struct tm *out_tm);
 int ossl_asn1_time_tm_to_time_t(const struct tm *tm, time_t *out);
+int ossl_asn1_call_aux_cb(const ASN1_AUX *aux, int operation,
+    const ASN1_VALUE **in, const ASN1_ITEM *it, void *exarg);

 #endif /* !defined(OSSL_LIBCRYPTO_ASN1_ASN1_LOCAL_H) */
diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c
index 834d087ebc..e489e29a0c 100644
--- a/crypto/asn1/tasn_enc.c
+++ b/crypto/asn1/tasn_enc.c
@@ -85,16 +85,10 @@ int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
     int i, seqcontlen, seqlen, ndef = 1;
     const ASN1_EXTERN_FUNCS *ef;
     const ASN1_AUX *aux = it->funcs;
-    ASN1_aux_const_cb *asn1_cb = NULL;

     if ((it->itype != ASN1_ITYPE_PRIMITIVE) && *pval == NULL)
         return 0;

-    if (aux != NULL) {
-        asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb
-                                                           : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */
-    }
-
     switch (it->itype) {

     case ASN1_ITYPE_PRIMITIVE:
@@ -123,7 +117,7 @@ int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
             ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
             return -1;
         }
-        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
+        if (!ossl_asn1_call_aux_cb(aux, ASN1_OP_I2D_PRE, pval, it, NULL))
             return 0;
         i = ossl_asn1_get_choice_selector_const(pval, it);
         if ((i >= 0) && (i < it->tcount)) {
@@ -134,7 +128,7 @@ int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
             return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
         }
         /* Fixme: error condition if selector out of range */
-        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
+        if (!ossl_asn1_call_aux_cb(aux, ASN1_OP_I2D_POST, pval, it, NULL))
             return 0;
         break;

@@ -166,7 +160,7 @@ int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
             aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
                 | V_ASN1_UNIVERSAL;
         }
-        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
+        if (!ossl_asn1_call_aux_cb(aux, ASN1_OP_I2D_PRE, pval, it, NULL))
             return 0;
         /* First work out sequence content length */
         for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
@@ -200,7 +194,7 @@ int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
         }
         if (ndef == 2)
             ASN1_put_eoc(out);
-        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
+        if (!ossl_asn1_call_aux_cb(aux, ASN1_OP_I2D_POST, pval, it, NULL))
             return 0;
         return seqlen;

diff --git a/crypto/asn1/tasn_prn.c b/crypto/asn1/tasn_prn.c
index 080b5623e4..72922c6530 100644
--- a/crypto/asn1/tasn_prn.c
+++ b/crypto/asn1/tasn_prn.c
@@ -138,15 +138,12 @@ static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent,
     const ASN1_EXTERN_FUNCS *ef;
     const ASN1_VALUE **tmpfld;
     const ASN1_AUX *aux = it->funcs;
-    ASN1_aux_const_cb *asn1_cb = NULL;
     ASN1_PRINT_ARG parg;
     int i;
     if (aux != NULL) {
         parg.out = out;
         parg.indent = indent;
         parg.pctx = pctx;
-        asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb
-                                                           : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */
     }

     if (((it->itype != ASN1_ITYPE_PRIMITIVE)
@@ -220,13 +217,11 @@ static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent,
             }
         }

-        if (asn1_cb) {
-            i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
-            if (i == 0)
-                return 0;
-            if (i == 2)
-                return 1;
-        }
+        i = ossl_asn1_call_aux_cb(aux, ASN1_OP_PRINT_PRE, fld, it, &parg);
+        if (i == 0)
+            return 0;
+        if (i == 2)
+            return 1;

         /* Print each field entry */
         for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
@@ -244,11 +239,9 @@ static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent,
                 return 0;
         }

-        if (asn1_cb) {
-            i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
-            if (i == 0)
-                return 0;
-        }
+        i = ossl_asn1_call_aux_cb(aux, ASN1_OP_PRINT_POST, fld, it, &parg);
+        if (i == 0)
+            return 0;
         break;

     default:
diff --git a/crypto/asn1/tasn_utl.c b/crypto/asn1/tasn_utl.c
index 5e82a10fbd..a4ab762960 100644
--- a/crypto/asn1/tasn_utl.c
+++ b/crypto/asn1/tasn_utl.c
@@ -288,3 +288,19 @@ err:
         ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
     return NULL;
 }
+
+int ossl_asn1_call_aux_cb(const ASN1_AUX *aux, int operation,
+    const ASN1_VALUE **in, const ASN1_ITEM *it, void *exarg)
+{
+    if (aux == NULL)
+        return 1;
+
+    if ((aux->flags & ASN1_AFLG_CONST_CB) != 0) {
+        if (aux->asn1_const_cb != NULL)
+            return aux->asn1_const_cb(operation, in, it, exarg);
+    } else if (aux->asn1_cb != NULL) {
+        return aux->asn1_cb(operation, (ASN1_VALUE **)in, it, exarg);
+    }
+
+    return 1;
+}