From 0edc9f313d4ef64f590f1749a95efa24e95d45c7 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 18 Jun 2024 09:16:28 +0200 Subject: [PATCH] fix panic on `xn--55555577` (#940) * reproduce a panic when parsing a specific URL Details can be found here: https://github.com/Byron/gitoxide/issues/1401 * fix overflow when processing punycode encoded URLs like `xn--55555577` * fix clippy error --- idna/src/punycode.rs | 3 +-- idna/tests/unit.rs | 6 ++++++ url/src/host.rs | 2 +- url/src/parser.rs | 4 ++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/idna/src/punycode.rs b/idna/src/punycode.rs index 436e40c02..6a3308890 100644 --- a/idna/src/punycode.rs +++ b/idna/src/punycode.rs @@ -17,7 +17,6 @@ use alloc::{string::String, vec::Vec}; use core::char; use core::fmt::Write; use core::marker::PhantomData; -use core::u32; // Bootstring parameters for Punycode const BASE: u32 = 36; @@ -215,7 +214,7 @@ impl Decoder { if C::EXTERNAL_CALLER && (digit > (u32::MAX - i) / weight) { return Err(()); // Overflow } - i += digit * weight; + i = i.checked_add(digit * weight).ok_or(())?; let t = if k <= bias { T_MIN } else if k >= bias + T_MAX { diff --git a/idna/tests/unit.rs b/idna/tests/unit.rs index b73f3b7ea..d0b24127a 100644 --- a/idna/tests/unit.rs +++ b/idna/tests/unit.rs @@ -40,6 +40,12 @@ fn test_punycode_prefix_without_length_check() { assert!(config.to_ascii("xn--.example.org").is_err()); } +#[test] +fn test_punycode_invalid_encoding() { + let config = idna::Config::default(); + assert!(config.to_ascii("xn--55555577").is_err()); +} + // http://www.unicode.org/reports/tr46/#Table_Example_Processing #[test] fn test_examples() { diff --git a/url/src/host.rs b/url/src/host.rs index 62db3b463..7864b77d6 100644 --- a/url/src/host.rs +++ b/url/src/host.rs @@ -309,7 +309,7 @@ fn parse_ipv4addr(input: &str) -> ParseResult { } let mut ipv4 = numbers.pop().expect("a non-empty list of numbers"); // Equivalent to: ipv4 >= 256 ** (4 − numbers.len()) - if ipv4 > u32::max_value() >> (8 * numbers.len() as u32) { + if ipv4 > u32::MAX >> (8 * numbers.len() as u32) { return Err(ParseError::InvalidIpv4Address); } if numbers.iter().any(|x| *x > 255) { diff --git a/url/src/parser.rs b/url/src/parser.rs index 2e3a4f644..8dd054df8 100644 --- a/url/src/parser.rs +++ b/url/src/parser.rs @@ -1109,7 +1109,7 @@ impl<'a> Parser<'a> { while let (Some(c), remaining) = input.split_first() { if let Some(digit) = c.to_digit(10) { port = port * 10 + digit; - if port > ::std::u16::MAX as u32 { + if port > u16::MAX as u32 { return Err(ParseError::InvalidPort); } has_any_digit = true; @@ -1590,7 +1590,7 @@ pub fn ascii_alpha(ch: char) -> bool { #[inline] pub fn to_u32(i: usize) -> ParseResult { - if i <= ::std::u32::MAX as usize { + if i <= u32::MAX as usize { Ok(i as u32) } else { Err(ParseError::Overflow)