From 329187ca76781997d3a01eafa23caac7f93779f7 Mon Sep 17 00:00:00 2001 From: tb <> Date: Tue, 9 Jun 2026 12:29:47 +0000 Subject: Add some missing bounds checks to ASN1_mbstring_copy() If the in string is unreasonably long, assigning strlen(in) to an int may overflow, so exclude this situation. Moreover, the code would unconditionally multiply nchar by 2 or 4, which could again overflow an int. Check for this situation and error out to avoid an out of bounds write. More may be needed in here, which will be revisited later. Based on a diff by Viktor Dukhovni via OpenSSL. --- src/lib/libcrypto/asn1/a_mbstr.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib/libcrypto/asn1/a_mbstr.c b/src/lib/libcrypto/asn1/a_mbstr.c index 38398ad1d1..21368543ce 100644 --- a/src/lib/libcrypto/asn1/a_mbstr.c +++ b/src/lib/libcrypto/asn1/a_mbstr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_mbstr.c,v 1.28 2025/05/10 05:54:38 tb Exp $ */ +/* $OpenBSD: a_mbstr.c,v 1.29 2026/06/09 12:29:47 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999. */ @@ -57,6 +57,7 @@ */ #include +#include #include #include @@ -105,8 +106,16 @@ ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, int nchar; int (*cpyfunc)(unsigned long, void *) = NULL; - if (len < 0) - len = strlen((const char *)in); + if (len < 0) { + size_t length; + + if ((length = strlen((const char *)in)) >= INT_MAX) { + ASN1error(ASN1_R_STRING_TOO_LONG); + return -1; + } + len = length; + } + if (!mask) mask = DIRSTRING_TYPE; @@ -221,11 +230,19 @@ ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, break; case MBSTRING_BMP: + if (nchar > INT_MAX / 2) { + ASN1error(ASN1_R_STRING_TOO_LONG); + goto err; + } outlen = nchar << 1; cpyfunc = cpy_bmp; break; case MBSTRING_UNIV: + if (nchar > INT_MAX / 4) { + ASN1error(ASN1_R_STRING_TOO_LONG); + goto err; + } outlen = nchar << 2; cpyfunc = cpy_univ; break; -- cgit v1.2.3-55-g6feb