From d3eb33dafd810151cd3688d586eb251684c31072 Mon Sep 17 00:00:00 2001 From: Skgland Date: Mon, 13 Nov 2023 19:39:11 +0100 Subject: [PATCH 1/3] add another overflowing test --- idna/src/punycode.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/idna/src/punycode.rs b/idna/src/punycode.rs index 8d26ce25e..8ce4923b2 100644 --- a/idna/src/punycode.rs +++ b/idna/src/punycode.rs @@ -311,3 +311,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); +} From 76441020859e2e2c229efc7fc703129244408306 Mon Sep 17 00:00:00 2001 From: Skgland Date: Mon, 13 Nov 2023 19:50:31 +0100 Subject: [PATCH 2/3] fix overflow in case the input has more than u32::MAX characters --- idna/src/punycode.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/idna/src/punycode.rs b/idna/src/punycode.rs index 8ce4923b2..fe432f80b 100644 --- a/idna/src/punycode.rs +++ b/idna/src/punycode.rs @@ -235,9 +235,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; From 9b16473b4df47d4e4b0299b83a7254670ccd280a Mon Sep 17 00:00:00 2001 From: Skgland Date: Mon, 13 Nov 2023 20:02:56 +0100 Subject: [PATCH 3/3] detect hugh length early --- idna/src/punycode.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/idna/src/punycode.rs b/idna/src/punycode.rs index fe432f80b..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()