Commit 6c92deff75 for openssl.org
commit 6c92deff75ad7fc31718d7fca0781c765c7941ae
Author: Koda Reef <koda.reef5@gmail.com>
Date: Sun Mar 22 21:44:21 2026 +0000
Add INT_MAX bounds check to d2i_ASN1_UINTEGER before (int)len cast
d2i_ASN1_UINTEGER uses (int)len for OPENSSL_malloc, memcpy, and
ASN1_STRING_set0 where len is a long. On LP64 platforms (long is
64-bit, int is 32-bit), values exceeding INT_MAX are silently
truncated, causing undersized allocation and heap buffer overflow.
The sibling function ossl_c2i_ASN1_BIT_STRING in a_bitstr.c already
has this guard (line 92: if (len > INT_MAX)). This adds the same
check to d2i_ASN1_UINTEGER for consistency.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Frederik Wedel-Heinen <fwh.openssl@gmail.com>
MergeDate: Fri Apr 3 15:22:30 2026
(Merged from https://github.com/openssl/openssl/pull/30532)
diff --git a/crypto/asn1/a_int.c b/crypto/asn1/a_int.c
index de39a54cdb..3b10ee99e5 100644
--- a/crypto/asn1/a_int.c
+++ b/crypto/asn1/a_int.c
@@ -441,11 +441,17 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
i = ASN1_R_ILLEGAL_NEGATIVE_VALUE;
goto err;
}
+#if INT_MAX < LONG_MAX
+ if (len > INT_MAX - 1) {
+ i = ASN1_R_TOO_LARGE;
+ goto err;
+ }
+#endif
/*
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
* a missing NULL parameter.
*/
- s = OPENSSL_malloc((int)len + 1);
+ s = OPENSSL_malloc(len == 0 ? 1 : (size_t)len);
if (s == NULL)
goto err;
ret->type = V_ASN1_INTEGER;
@@ -454,11 +460,11 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
p++;
len--;
}
- memcpy(s, p, (int)len);
+ memcpy(s, p, (size_t)len);
p += len;
}
- ASN1_STRING_set0(ret, s, (int)len);
+ ASN1_STRING_set0(ret, s, (int)len); /* len <= INT_MAX checked above */
if (a != NULL)
(*a) = ret;
*pp = p;