From e9251e1fc153692e613e9d8a7606bd6e4ac117b1 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Wed, 18 Dec 2019 13:21:37 +0200 Subject: [PATCH] In UTF-16[BE|LE] decoder with last=true, check space without intent to write if the decoder has pending state. This ensures that the outer caller has space for the REPLACEMENT CHARACTER as happens more naturally with other encodings. Closes #44. --- src/utf_16.rs | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/utf_16.rs b/src/utf_16.rs index e6f0fb1f..9ae41b0a 100644 --- a/src/utf_16.rs +++ b/src/utf_16.rs @@ -90,24 +90,31 @@ impl Utf16Decoder { }, { debug_assert!(!self.pending_bmp); - if self.lead_surrogate != 0 { - self.lead_surrogate = 0; - match self.lead_byte { - None => { - return (DecoderResult::Malformed(2, 0), src_consumed, dest.written()); + if self.lead_surrogate != 0 || self.lead_byte.is_some() { + // We need to check space without intent to write in order to + // make sure that there is space for the replacement character. + match dest.check_space_bmp() { + Space::Full(_) => { + return (DecoderResult::OutputFull, 0, 0); } - Some(_) => { + Space::Available(_) => { + if self.lead_surrogate != 0 { + self.lead_surrogate = 0; + match self.lead_byte { + None => { + return (DecoderResult::Malformed(2, 0), src_consumed, dest.written()); + } + Some(_) => { + self.lead_byte = None; + return (DecoderResult::Malformed(3, 0), src_consumed, dest.written()); + } + } + } + debug_assert!(self.lead_byte.is_some()); self.lead_byte = None; - return (DecoderResult::Malformed(3, 0), src_consumed, dest.written()); + return (DecoderResult::Malformed(1, 0), src_consumed, dest.written()); } - } - } - match self.lead_byte { - None => {} - Some(_) => { - self.lead_byte = None; - return (DecoderResult::Malformed(1, 0), src_consumed, dest.written()); - } + } } }, {