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 {