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;
+}