From 8d0ed289e4f04e3a1504b59a17d2cbccb5acf9aa Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 24 Jul 2023 10:08:37 -0600 Subject: [PATCH] Attempt to error on characters outside Basic Multilingual Plane Ensure all codepoints fit in `u16`. --- der/src/asn1/bmp_string.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/der/src/asn1/bmp_string.rs b/der/src/asn1/bmp_string.rs index c2dc2d85d..846b653d0 100644 --- a/der/src/asn1/bmp_string.rs +++ b/der/src/asn1/bmp_string.rs @@ -29,10 +29,12 @@ impl BmpString { bytes: bytes.try_into()?, }; - // Ensure resulting string is free of unpaired surrogates for maybe_char in char::decode_utf16(ret.codepoints()) { - if maybe_char.is_err() { - return Err(Tag::BmpString.value_error()); + match maybe_char { + // All surrogates paired and character is in the Basic Multilingual Plane + Ok(c) if (c as u64) < (u16::MAX as u64) => (), + // Unpaired surrogates or characters outside Basic Multilingual Plane + _ => return Err(Tag::BmpString.value_error()), } } @@ -41,16 +43,18 @@ impl BmpString { /// Create a new [`BmpString`] from a UTF-8 string. pub fn from_utf8(utf8: &str) -> Result { - #[allow(clippy::integer_arithmetic)] - let mut bytes = Vec::with_capacity(utf8.len() * 2); + let capacity = utf8 + .len() + .checked_mul(2) + .ok_or_else(|| Tag::BmpString.length_error())?; + + let mut bytes = Vec::with_capacity(capacity); for code_point in utf8.encode_utf16() { bytes.extend(code_point.to_be_bytes()); } - Ok(Self { - bytes: bytes.try_into()?, - }) + Self::from_ucs2(bytes) } /// Borrow the encoded UCS-2 as bytes.