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) \