From 464b1f7d8fe9de117af184c1acb52b4f821a0cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bennet=20Ble=C3=9Fmann?= Date: Fri, 17 Nov 2023 12:01:09 +0100 Subject: [PATCH] Fix another overflow in punycode encode_into (#880) * add another overflowing test * fix overflow in case the input has more than u32::MAX characters * detect hugh length early --- idna/src/punycode.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/idna/src/punycode.rs b/idna/src/punycode.rs index 8d26ce25e..b1afc96f7 100644 --- a/idna/src/punycode.rs +++ b/idna/src/punycode.rs @@ -215,6 +215,9 @@ impl<'a> ExactSizeIterator for Decode<'a> { /// This is a convenience wrapper around `encode`. #[inline] pub fn encode_str(input: &str) -> Option { + if input.len() > u32::MAX as usize { + return None; + } let mut buf = String::with_capacity(input.len()); encode_into(input.chars(), &mut buf).ok().map(|()| buf) } @@ -224,6 +227,9 @@ pub fn encode_str(input: &str) -> Option { /// Return None on overflow, which can only happen on inputs that would take more than /// 63 encoded bytes, the DNS limit on domain name labels. pub fn encode(input: &[char]) -> Option { + if input.len() > u32::MAX as usize { + return None; + } let mut buf = String::with_capacity(input.len()); encode_into(input.iter().copied(), &mut buf) .ok() @@ -235,9 +241,9 @@ where I: Iterator + Clone, { // Handle "basic" (ASCII) code points. They are encoded as-is. - let (mut input_length, mut basic_length) = (0, 0); + let (mut input_length, mut basic_length) = (0u32, 0); for c in input.clone() { - input_length += 1; + input_length = input_length.checked_add(1).ok_or(())?; if c.is_ascii() { output.push(c); basic_length += 1; @@ -311,3 +317,12 @@ fn value_to_digit(value: u32) -> char { _ => panic!(), } } + +#[test] +#[ignore = "slow"] +#[cfg(target_pointer_width = "64")] +fn huge_encode() { + let mut buf = String::new(); + assert!(encode_into(std::iter::repeat('ß').take(u32::MAX as usize + 1), &mut buf).is_err()); + assert_eq!(buf.len(), 0); +}