From 64433a447edee225e7910320987e73f9aee932af Mon Sep 17 00:00:00 2001 From: Philipp Korber Date: Thu, 14 Feb 2019 20:13:54 +0100 Subject: fix(internals): Fixed bug where linebrakig could panic. --- headers/src/header_components/unstructured.rs | 12 ++++++++++++ internals/src/encoder/mod.rs | 26 +++++++++++++------------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/headers/src/header_components/unstructured.rs b/headers/src/header_components/unstructured.rs index 84a4912..76d1da6 100644 --- a/headers/src/header_components/unstructured.rs +++ b/headers/src/header_components/unstructured.rs @@ -191,4 +191,16 @@ mod test { MarkFWS, Text " \t " ]} + + ec_test!{ long_mixed_input, { + Unstructured::try_from("Subject: …. AAAAAAAAAAAAAAAAAAA….. AA…")? + } => ascii => [ + Text "Subject:", + MarkFWS, + Text " =?utf8?Q?=E2=80=A6=2E?=", + MarkFWS, + Text " =?utf8?Q?AAAAAAAAAAAAAAAAAAA=E2=80=A6=2E=2E?=", + MarkFWS, + Text " =?utf8?Q?AA=E2=80=A6?=" + ]} } \ No newline at end of file diff --git a/internals/src/encoder/mod.rs b/internals/src/encoder/mod.rs index 52a9fb2..b7703e5 100644 --- a/internals/src/encoder/mod.rs +++ b/internals/src/encoder/mod.rs @@ -47,6 +47,9 @@ pub const LINE_LEN_SOFT_LIMIT: usize = 78; /// as specified in RFC 5322 (mail) + RFC 5321 (smtp) not including CRLF pub const LINE_LEN_HARD_LIMIT: usize = 998; +pub const NEWLINE: &str = "\r\n"; +pub const NEWLINE_WITH_SPACE: &str = "\r\n "; + /// EncodingBuffer for a Mail providing a buffer for encodable traits. pub struct EncodingBuffer { @@ -113,7 +116,7 @@ impl EncodingBuffer { pub fn write_blank_line(&mut self) { //TODO/BENCH push_str vs. extends(&[u8]) - self.buffer.extend("\r\n".as_bytes()); + self.buffer.extend(NEWLINE.as_bytes()); #[cfg(feature="traceing")] { self.trace.push(TraceToken::BlankLine); } } @@ -122,8 +125,8 @@ impl EncodingBuffer { pub fn write_body_unchecked(&mut self, body: &impl AsRef<[u8]>) { let slice = body.as_ref(); self.buffer.extend(slice); - if !slice.ends_with(b"\r\n") { - self.buffer.extend(b"\r\n"); + if !slice.ends_with(NEWLINE.as_bytes()) { + self.buffer.extend(NEWLINE.as_bytes()); } } @@ -648,20 +651,17 @@ impl<'inner> EncodingWriter<'inner> { fn break_line_on_fws(&mut self) -> bool { if self.content_before_fws && self.last_fws_idx > self.line_start_idx { - //INDEX_SAFE: self.content_before_fws is only true if there is at last one char - // if so self.last_ws_idx does not point at the end of the buffer but inside - let newline = match self.buffer[self.last_fws_idx] { - b' ' | b'\t' => "\r\n", - _ => "\r\n " - }; + + let newline = self.buffer.get(self.last_fws_idx) + .map(|bch| match bch { + b' ' | b'\t' => NEWLINE, + _ => NEWLINE_WITH_SPACE + }) + .unwrap_or(NEWLINE_WITH_SPACE); vec_insert_bytes(&mut self.buffer, self.last_fws_idx, newline.as_bytes()); self.line_start_idx = self.last_fws_idx + 2; - // no need last_fws can be < line_start but - //self.last_fws_idx = self.line_start_idx; self.content_before_fws = false; - // stays the same: - //self.content_since_fws = self.content_since_fws true } else { false -- cgit v1.2.3