Commit 4cef487f2a for openssl.org
commit 4cef487f2a5615e59d919e6fd4094a02038950ff
Author: Norbert Pocs <norbertp@openssl.org>
Date: Sat Jul 18 16:49:06 2026 +0200
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 <norbertp@openssl.org>
Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
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 e488c87f5b..57a14f6f90 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 d31c74ef45..408c2a1548 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 90588c8c67..961f474e5b 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;