Commit f6efce32a0 for openssl.org

commit f6efce32a024298a1b3d87ec4914d49bcab34366
Author: Nikola Pajkovsky <nikolap@openssl.org>
Date:   Tue May 19 11:39:41 2026 +0200

    avoid mismatched d2i callbacks in PEM readers

    decode PEM payloads through the generated typed d2i_* functions in the
    PEM read macros instead of routing them through the d2i_of_void
    callback path. This avoids UBSan function type mismatch reports while
    preserving the public PEM reader APIs.

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

    Reviewed-by: Neil Horman <nhorman@openssl.org>
    Reviewed-by: Milan Broz <mbroz@openssl.org>
    MergeDate: Thu Jun 25 12:12:57 2026
    (Merged from https://github.com/openssl/openssl/pull/31523)

diff --git a/include/openssl/pem.h b/include/openssl/pem.h
index ccde1b93d5..115c8f2733 100644
--- a/include/openssl/pem.h
+++ b/include/openssl/pem.h
@@ -117,8 +117,26 @@ extern "C" {
 #define IMPLEMENT_PEM_read_fp(name, type, str, asn1)                        \
     type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u) \
     {                                                                       \
-        return PEM_ASN1_read((d2i_of_void *)d2i_##asn1, str, fp,            \
-            (void **)x, cb, u);                                             \
+        BIO *b;                                                             \
+        const unsigned char *p = NULL;                                      \
+        unsigned char *data = NULL;                                         \
+        long len;                                                           \
+        type *ret = NULL;                                                   \
+                                                                            \
+        if ((b = BIO_new(BIO_s_file())) == NULL) {                          \
+            ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB);                          \
+            return NULL;                                                    \
+        }                                                                   \
+        BIO_set_fp(b, fp, BIO_NOCLOSE);                                     \
+        if (PEM_bytes_read_bio(&data, &len, NULL, str, b, cb, u)) {         \
+            p = data;                                                       \
+            ret = d2i_##asn1(x, &p, len);                                   \
+            if (ret == NULL)                                                \
+                ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB);                     \
+        }                                                                   \
+        BIO_free(b);                                                        \
+        OPENSSL_free(data);                                                 \
+        return ret;                                                         \
     }

 #define IMPLEMENT_PEM_write_fp(name, type, str, asn1)              \
@@ -146,12 +164,24 @@ extern "C" {
 #endif
 #endif

-#define IMPLEMENT_PEM_read_bio(name, type, str, asn1)                \
-    type *PEM_read_bio_##name(BIO *bp, type **x,                     \
-        pem_password_cb *cb, void *u)                                \
-    {                                                                \
-        return PEM_ASN1_read_bio((d2i_of_void *)d2i_##asn1, str, bp, \
-            (void **)x, cb, u);                                      \
+#define IMPLEMENT_PEM_read_bio(name, type, str, asn1)   \
+    type *PEM_read_bio_##name(BIO *bp, type **x,        \
+        pem_password_cb *cb, void *u)                   \
+    {                                                   \
+        const unsigned char *p = NULL;                  \
+        unsigned char *data = NULL;                     \
+        long len;                                       \
+        type *ret = NULL;                               \
+                                                        \
+        if (!PEM_bytes_read_bio(&data, &len, NULL, str, \
+                bp, cb, u))                             \
+            return NULL;                                \
+        p = data;                                       \
+        ret = d2i_##asn1(x, &p, len);                   \
+        if (ret == NULL)                                \
+            ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB);     \
+        OPENSSL_free(data);                             \
+        return ret;                                     \
     }

 #define IMPLEMENT_PEM_write_bio(name, type, str, asn1)                 \