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)
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;
unsigned char *p, *q;
char hextmp[2];
+ if (buflen < 0)
+ return -1;
+ if (buflen == 0)
+ return 0;
if (arg) {
p = buf;
q = buf + buflen;
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;
}
if (!ASN1_OCTET_STRING_set(os, *pp, length))
goto err;
- *pp += length;
+ if (length > 0)
+ *pp += length;
if (pos)
*pos = os;
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;