Commit 3a19032449 for openssl.org
commit 3a19032449a22ed115651cdd0212ccab19ac9a83
Author: Eugene Syromiatnikov <esyr@openssl.org>
Date: Mon Sep 14 15:38:16 2026 +0200
crypto/asn1: add checks for possibly negative ASN1_STRING length
ASN1_STRING_length_set() allows setting ASN1_STRING's length
to an arbitrary int value, including negative ones. While some places
do perform sanity checks of the length value, others do not; add some
missing checks.
Signed-off-by: Eugene Syromiatnikov <esyr@openssl.org>
Reviewed-by: Bob Beck <beck@openssl.org>
Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
Merge-date: Thu Sep 17 14:00:09 2026
Merged-from: https://github.com/openssl/openssl/pull/32825
diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c
index fdefb80e26..02180541ea 100644
--- a/crypto/asn1/a_bitstr.c
+++ b/crypto/asn1/a_bitstr.c
@@ -32,7 +32,7 @@ int ossl_i2c_ASN1_BIT_STRING(const ASN1_BIT_STRING *a, unsigned char **pp)
len = a->length;
- if (len > INT_MAX - 1)
+ if (len > INT_MAX - 1 || len < 0)
goto err;
if ((len > 0) && (a->flags & ASN1_STRING_FLAG_BITS_LEFT))
@@ -224,7 +224,7 @@ int ASN1_BIT_STRING_get_length(const ASN1_BIT_STRING *abs, size_t *out_length,
if (abs == NULL || abs->type != V_ASN1_BIT_STRING)
return 0;
- if (out_length == NULL || out_unused_bits == NULL)
+ if (out_length == NULL || out_unused_bits == NULL || abs->length < 0)
return 0;
length = abs->length;
diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c
index 5f1b14bf3e..4bf03be0b4 100644
--- a/crypto/asn1/asn1_lib.c
+++ b/crypto/asn1/asn1_lib.c
@@ -374,7 +374,10 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in)
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
{
if (!(str->flags & ASN1_STRING_FLAG_DATA_NOT_OWNED)) {
- OPENSSL_clear_free(str->data, str->length);
+ if (str->length > 0)
+ OPENSSL_clear_free(str->data, str->length);
+ else
+ OPENSSL_free(str->data);
}
str->flags &= ~ASN1_STRING_FLAG_DATA_NOT_OWNED;
str->data = data;
@@ -455,7 +458,7 @@ void ossl_asn1_string_free_internal(ASN1_STRING *a, int clear, int embed)
}
if (!(a->flags & ASN1_STRING_FLAG_NDEF)) {
- if (clear)
+ if (clear && a->length > 0)
OPENSSL_clear_free(a->data, a->length);
else
OPENSSL_free(a->data);
@@ -514,7 +517,7 @@ int ASN1_STRING_length(const ASN1_STRING *x)
size_t ASN1_STRING_get_length(const ASN1_STRING *x)
{
- return (size_t)x->length;
+ return x->length >= 0 ? (size_t)x->length : 0U;
}
#ifndef OPENSSL_NO_DEPRECATED_3_0