Skip to content

Commit 464b1f7

Browse files
authored
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
1 parent 912d716 commit 464b1f7

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

idna/src/punycode.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ impl<'a> ExactSizeIterator for Decode<'a> {
215215
/// This is a convenience wrapper around `encode`.
216216
#[inline]
217217
pub fn encode_str(input: &str) -> Option<String> {
218+
if input.len() > u32::MAX as usize {
219+
return None;
220+
}
218221
let mut buf = String::with_capacity(input.len());
219222
encode_into(input.chars(), &mut buf).ok().map(|()| buf)
220223
}
@@ -224,6 +227,9 @@ pub fn encode_str(input: &str) -> Option<String> {
224227
/// Return None on overflow, which can only happen on inputs that would take more than
225228
/// 63 encoded bytes, the DNS limit on domain name labels.
226229
pub fn encode(input: &[char]) -> Option<String> {
230+
if input.len() > u32::MAX as usize {
231+
return None;
232+
}
227233
let mut buf = String::with_capacity(input.len());
228234
encode_into(input.iter().copied(), &mut buf)
229235
.ok()
@@ -235,9 +241,9 @@ where
235241
I: Iterator<Item = char> + Clone,
236242
{
237243
// Handle "basic" (ASCII) code points. They are encoded as-is.
238-
let (mut input_length, mut basic_length) = (0, 0);
244+
let (mut input_length, mut basic_length) = (0u32, 0);
239245
for c in input.clone() {
240-
input_length += 1;
246+
input_length = input_length.checked_add(1).ok_or(())?;
241247
if c.is_ascii() {
242248
output.push(c);
243249
basic_length += 1;
@@ -311,3 +317,12 @@ fn value_to_digit(value: u32) -> char {
311317
_ => panic!(),
312318
}
313319
}
320+
321+
#[test]
322+
#[ignore = "slow"]
323+
#[cfg(target_pointer_width = "64")]
324+
fn huge_encode() {
325+
let mut buf = String::new();
326+
assert!(encode_into(std::iter::repeat('ß').take(u32::MAX as usize + 1), &mut buf).is_err());
327+
assert_eq!(buf.len(), 0);
328+
}

0 commit comments

Comments
 (0)