From: Norbert Pocs Date: Sat, 18 Jul 2026 14:49:06 +0000 (+0200) Subject: Guard against NULL data in empty ASN1_STRINGs X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4cef487f2a5615e59d919e6fd4094a02038950ff;p=thirdparty%2Fopenssl.git Guard against NULL data in empty ASN1_STRINGs Since 28179061bf a zero-length ASN1_STRING has data == NULL in fuzzing builds instead of a 1-byte allocation. Several call sites did pointer arithmetic or memcpy on the data pointer before any length check, which is undefined behaviour for NULL even with a zero offset and aborts the fuzz targets under UBSan: - asn1_string_canon: skip canonicalisation of empty values - do_buf, do_hex_dump: return early on an empty buffer - i2d_ocsp_nonce: skip the memcpy for an empty nonce The loops at these sites were already no-ops for zero length, so there is no behaviour change outside sanitizer builds. Assisted-By: Claude:claude-fable-5 Signed-off-by: Norbert Pocs Reviewed-by: Nikola Pajkovsky Reviewed-by: Tomas Mraz MergeDate: Tue Jul 21 12:54:48 2026 (Merged from https://github.com/openssl/openssl/pull/31998) --- diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c index e488c87f5bc..57a14f6f90c 100644 --- a/crypto/asn1/a_strex.c +++ b/crypto/asn1/a_strex.c @@ -142,6 +142,10 @@ static int do_buf(const unsigned char *buf, int buflen, const unsigned char *p, *q; uint32_t c; + if (buflen < 0) + return -1; + if (buflen == 0) + return 0; p = buf; q = buf + buflen; outlen = 0; @@ -236,6 +240,10 @@ static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, unsigned char *p, *q; char hextmp[2]; + if (buflen < 0) + return -1; + if (buflen == 0) + return 0; if (arg) { p = buf; q = buf + buflen; diff --git a/crypto/ocsp/v3_ocsp.c b/crypto/ocsp/v3_ocsp.c index d31c74ef453..408c2a15486 100644 --- a/crypto/ocsp/v3_ocsp.c +++ b/crypto/ocsp/v3_ocsp.c @@ -143,7 +143,7 @@ static void *ocsp_nonce_new(void) static int i2d_ocsp_nonce(const void *a, unsigned char **pp) { const ASN1_OCTET_STRING *os = a; - if (pp) { + if (pp != NULL && os->length > 0) { memcpy(*pp, os->data, os->length); *pp += os->length; } @@ -164,7 +164,8 @@ static void *d2i_ocsp_nonce(void *a, const unsigned char **pp, long length) if (!ASN1_OCTET_STRING_set(os, *pp, length)) goto err; - *pp += length; + if (length > 0) + *pp += length; if (pos) *pos = os; diff --git a/crypto/x509/x_name.c b/crypto/x509/x_name.c index 90588c8c67e..961f474e5b4 100644 --- a/crypto/x509/x_name.c +++ b/crypto/x509/x_name.c @@ -404,8 +404,10 @@ static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in) out->type = V_ASN1_UTF8STRING; out->length = ASN1_STRING_to_UTF8(&out->data, in); - if (out->length == -1) + if (out->length < 0) return 0; + if (out->length == 0) + return 1; to = out->data; from = to;