Skip to content

Commit 8b6f5f5

Browse files
committed
check for >2 bytes long chars
1 parent 63c30cf commit 8b6f5f5

2 files changed

Lines changed: 35 additions & 1 deletion

File tree

der/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ derive = ["dep:der_derive"]
3939
oid = ["dep:const-oid"]
4040
pem = ["dep:pem-rfc7468", "alloc", "zeroize"]
4141
real = []
42+
hazmat = []
4243

4344
[package.metadata.docs.rs]
4445
all-features = true

der/src/asn1/bmp_string.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ impl BmpString {
4444
#[allow(clippy::integer_arithmetic)]
4545
let mut bytes = Vec::with_capacity(utf8.len() * 2);
4646

47+
if utf8.chars().any(|c| c.len_utf16() != 1) {
48+
return Err(Tag::BmpString.value_error());
49+
}
50+
4751
for code_point in utf8.encode_utf16() {
4852
bytes.extend(code_point.to_be_bytes());
4953
}
@@ -77,6 +81,24 @@ impl BmpString {
7781
.chunks_exact(2)
7882
.map(|chunk| u16::from_be_bytes(chunk.try_into().expect("two bytes")))
7983
}
84+
85+
#[cfg(feature = "hazmat")]
86+
/// Create a new [`BmpString`] from bytes.
87+
///
88+
/// It bypasses the check for utf16 encoding of its values.
89+
pub fn new_unchecked(bytes: impl Into<Box<[u8]>>) -> Result<Self> {
90+
let bytes = bytes.into();
91+
92+
if bytes.len() % 2 != 0 {
93+
return Err(Tag::BmpString.length_error());
94+
}
95+
96+
let ret = Self {
97+
bytes: bytes.try_into()?,
98+
};
99+
100+
Ok(ret)
101+
}
80102
}
81103

82104
impl AsRef<[u8]> for BmpString {
@@ -131,7 +153,7 @@ impl fmt::Display for BmpString {
131153
#[cfg(test)]
132154
mod tests {
133155
use super::BmpString;
134-
use crate::{Decode, Encode};
156+
use crate::{Decode, Encode, Tag};
135157
use alloc::string::ToString;
136158
use hex_literal::hex;
137159

@@ -157,4 +179,15 @@ mod tests {
157179
let encoded = bmp_string.to_der().unwrap();
158180
assert_eq!(encoded, EXAMPLE_BYTES);
159181
}
182+
183+
#[test]
184+
fn encode_errors() {
185+
let err = BmpString::from_utf8("🔥");
186+
assert_eq!(err, Err(Tag::BmpString.value_error()));
187+
188+
#[cfg(feature = "hazmat")]
189+
{
190+
assert!(BmpString::new_unchecked("🔥".as_bytes()).is_ok());
191+
}
192+
}
160193
}

0 commit comments

Comments
 (0)