diff --git a/src/utf_16.rs b/src/utf_16.rs index 41f6392..688e2f4 100644 --- a/src/utf_16.rs +++ b/src/utf_16.rs @@ -29,8 +29,13 @@ impl Utf16Decoder { } pub fn additional_from_state(&self) -> usize { + // A pending BMP code unit is stored in `lead_surrogate` and may be zero. 1 + if self.lead_byte.is_some() { 1 } else { 0 } - + if self.lead_surrogate == 0 { 0 } else { 2 } + + if self.lead_surrogate == 0 && !self.pending_bmp { + 0 + } else { + 2 + } } pub fn max_utf16_buffer_length(&self, byte_length: usize) -> Option { @@ -444,6 +449,34 @@ mod tests { } } + #[test] + fn test_utf_16le_pending_nul_max_length() { + // An unpaired high surrogate followed by U+0000 leaves U+0000 pending. + // The max length queries must count it like any other pending code unit. + let mut decoder = UTF_16LE.new_decoder_without_bom_handling(); + let mut output = [0u8; 16]; + let (result, _, _) = + decoder.decode_to_utf8_without_replacement(&[0x00, 0xD8], &mut output[..], false); + assert_eq!(result, DecoderResult::InputEmpty); + let (result, read, _) = decoder.decode_to_utf8_without_replacement( + &[0x00, 0x00, 0x00, 0x4E, 0x00, 0x4E], + &mut output[..], + false, + ); + assert_eq!(result, DecoderResult::Malformed(2, 2)); + assert_eq!(read, 2); + let rest = [0x00, 0x4E, 0x00, 0x4E]; + let max = decoder + .max_utf8_buffer_length_without_replacement(rest.len()) + .unwrap(); + let mut output = vec![0u8; max]; + let (result, read, written) = + decoder.decode_to_utf8_without_replacement(&rest, &mut output[..], true); + assert_eq!(result, DecoderResult::InputEmpty); + assert_eq!(read, 4); + assert_eq!(&output[..written], "\u{0000}\u{4E00}\u{4E00}".as_bytes()); + } + #[test] fn test_utf_16be_decode_near_end() { let mut output = [0u8; 4];