]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Guard against NULL data in empty ASN1_STRINGs
authorNorbert Pocs <norbertp@openssl.org>
Sat, 18 Jul 2026 14:49:06 +0000 (16:49 +0200)
committerNorbert Pocs <norbertp@openssl.org>
Tue, 21 Jul 2026 12:54:46 +0000 (14:54 +0200)
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)

crypto/asn1/a_strex.c
crypto/ocsp/v3_ocsp.c
crypto/x509/x_name.c

index e488c87f5bce2b0938843dfe0291bb2473202f67..57a14f6f90c10a04fe63b91584eb0384f3449e18 100644 (file)
@@ -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;
index d31c74ef453f7a15a0cc0bfbd5f1a056e1e5b0f3..408c2a15486ffbf80d0850940f9a1b295912272b 100644 (file)
@@ -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;
index 90588c8c67ea6630ba662fcdbf7bce756116a768..961f474e5b42e2030200c0df80ffb49a0bb17885 100644 (file)
@@ -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;