Upgrade idna to 0.5.0 This project was upgraded with external_updater. Usage: tools/external_updater/updater.sh update external/rust/crates/idna For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md Test: TreeHugger Change-Id: I96d7c0adb55f3ef853a1acee00c92f64964c832a
diff --git a/src/lib.rs b/src/lib.rs index 37d6387..92914f9 100644 --- a/src/lib.rs +++ b/src/lib.rs
@@ -31,11 +31,23 @@ //! > This document specifies a mechanism //! > that minimizes the impact of this transition for client software, //! > allowing client software to access domains that are valid under either system. +#![no_std] + +// For forwards compatibility +#[cfg(feature = "std")] +extern crate std; + +extern crate alloc; + +#[cfg(not(feature = "alloc"))] +compile_error!("the `alloc` feature must be enabled"); #[cfg(test)] #[macro_use] extern crate assert_matches; +use alloc::string::String; + pub mod punycode; mod uts46;
diff --git a/src/punycode.rs b/src/punycode.rs index 21955f3..b1afc96 100644 --- a/src/punycode.rs +++ b/src/punycode.rs
@@ -13,8 +13,9 @@ //! `encode_str` and `decode_to_string` provide convenience wrappers //! that convert from and to Rust’s UTF-8 based `str` and `String` types. -use std::char; -use std::u32; +use alloc::{string::String, vec::Vec}; +use core::char; +use core::u32; // Bootstring parameters for Punycode static BASE: u32 = 36; @@ -168,7 +169,7 @@ } pub(crate) struct Decode<'a> { - base: std::str::Chars<'a>, + base: core::str::Chars<'a>, pub(crate) insertions: &'a [(usize, char)], inserted: usize, position: usize, @@ -214,6 +215,9 @@ /// This is a convenience wrapper around `encode`. #[inline] pub fn encode_str(input: &str) -> Option<String> { + 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) } @@ -223,6 +227,9 @@ /// 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<String> { + 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() @@ -234,9 +241,9 @@ I: Iterator<Item = char> + 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; @@ -268,10 +275,7 @@ for c in input.clone() { let c = c as u32; if c < code_point { - delta += 1; - if delta == 0 { - return Err(()); // Overflow - } + delta = delta.checked_add(1).ok_or(())?; } if c == code_point { // Represent delta as a generalized variable-length integer: @@ -313,3 +317,12 @@ _ => 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); +}
diff --git a/src/uts46.rs b/src/uts46.rs index ec2fd0b..b082416 100644 --- a/src/uts46.rs +++ b/src/uts46.rs
@@ -11,7 +11,9 @@ use self::Mapping::*; use crate::punycode; -use std::{error::Error as StdError, fmt}; + +use alloc::string::String; +use core::fmt; use unicode_bidi::{bidi_class, BidiClass}; use unicode_normalization::char::is_combining_mark; use unicode_normalization::{is_nfc, UnicodeNormalization}; @@ -70,10 +72,10 @@ } struct Mapper<'a> { - chars: std::str::Chars<'a>, + chars: core::str::Chars<'a>, config: Config, errors: &'a mut Errors, - slice: Option<std::str::Chars<'static>>, + slice: Option<core::str::Chars<'static>>, } impl<'a> Iterator for Mapper<'a> { @@ -274,7 +276,7 @@ /// http://www.unicode.org/reports/tr46/#Validity_Criteria fn check_validity(label: &str, config: Config, errors: &mut Errors) { let first_char = label.chars().next(); - if first_char == None { + if first_char.is_none() { // Empty string, pass return; } @@ -451,7 +453,7 @@ return Errors::default(); } let mut errors = processing(domain, self.config, &mut self.normalized, out); - self.output = std::mem::replace(out, String::with_capacity(out.len())); + self.output = core::mem::replace(out, String::with_capacity(out.len())); let mut first = true; for label in self.output.split('.') { if !first { @@ -475,7 +477,7 @@ /// http://www.unicode.org/reports/tr46/#ToASCII #[allow(clippy::wrong_self_convention)] - pub fn to_ascii<'a>(&'a mut self, domain: &str, out: &mut String) -> Result<(), Errors> { + pub fn to_ascii(&mut self, domain: &str, out: &mut String) -> Result<(), Errors> { let mut errors = self.to_ascii_inner(domain, out); if self.config.verify_dns_length { @@ -497,7 +499,7 @@ /// http://www.unicode.org/reports/tr46/#ToUnicode #[allow(clippy::wrong_self_convention)] - pub fn to_unicode<'a>(&'a mut self, domain: &str, out: &mut String) -> Result<(), Errors> { + pub fn to_unicode(&mut self, domain: &str, out: &mut String) -> Result<(), Errors> { if is_simple(domain) { out.push_str(domain); return Errors::default().into(); @@ -507,6 +509,7 @@ } #[derive(Clone, Copy)] +#[must_use] pub struct Config { use_std3_ascii_rules: bool, transitional_processing: bool, @@ -685,7 +688,7 @@ if !empty { f.write_str(", ")?; } - f.write_str(*name)?; + f.write_str(name)?; empty = false; } } @@ -708,7 +711,8 @@ } } -impl StdError for Errors {} +#[cfg(feature = "std")] +impl std::error::Error for Errors {} impl fmt::Display for Errors { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {