Bug 1454257 - handle empty continuation line correctly. r=aceman a=jorgk
authorJorg K <jorgk@jorgk.com>
Mon, 23 Apr 2018 00:56:35 +0200
changeset 31414 ef08af42ccdff19d0c8317d73674a7dd43d9c7b3
parent 31413 8e864de65e00f4ecf1d213b5cccc091aeff3b051
child 31415 2ed7c90c8ab0e9c3bc5fe621300092f1d15d0e28
push id383
push userclokep@gmail.com
push dateMon, 07 May 2018 21:52:48 +0000
reviewersaceman, jorgk
bugs1454257
Bug 1454257 - handle empty continuation line correctly. r=aceman a=jorgk
mailnews/local/src/nsParseMailbox.cpp
--- a/mailnews/local/src/nsParseMailbox.cpp
+++ b/mailnews/local/src/nsParseMailbox.cpp
@@ -1062,54 +1062,52 @@ nsresult nsParseMailMessageState::ParseH
 
       ToLowerCase(headerStr);
       size_t customHeaderIndex = m_customDBHeaders.IndexOf(headerStr);
       if (customHeaderIndex != m_customDBHeaders.NoIndex)
         header = & m_customDBHeaderValues[customHeaderIndex];
     }
 
     buf = colon + 1;
-    uint32_t writeOffset = 0; // number of characters replaced with a folded space
+    // We will be shuffling downwards, so this is our insertion point.
+    char *bufWrite = buf;
 
 SEARCH_NEWLINE:
     // move past any non terminating characters, rewriting them if folding white space
     // exists
     while (buf < buf_end && *buf != '\r' && *buf != '\n')
     {
-      if (writeOffset)
-        *(buf - writeOffset) = *buf;
+      // Compress white-space.
+      if ((*buf == ' ' || *buf == '\t') &&
+          (*(bufWrite - 1) == ' ' || *(bufWrite - 1) == '\t')) {
+         buf++;
+         continue;
+      }
+      if (buf != bufWrite)
+        *bufWrite = *buf;
       buf++;
+      bufWrite++;
     }
 
-    /* If "\r\n " or "\r\n\t" is next, that doesn't terminate the header. */
+    // Look for folding, so CRLF, CR or LF followed by space or tab.
     if ((buf + 2 < buf_end && (buf[0] == '\r' && buf[1] == '\n') &&
                               (buf[2] == ' ' || buf[2] == '\t')) ||
-    /* If "\r " or "\r\t" or "\n " or "\n\t" is next, that doesn't terminate
-       the header either. */
         (buf + 1 < buf_end && (buf[0] == '\r' || buf[0] == '\n') &&
                               (buf[1] == ' ' || buf[1] == '\t')))
     {
-      // locate the proper location for a folded space by eliminating any
-      // leading spaces before the end-of-line character
-      char* foldedSpace = buf;
-      while (*(foldedSpace - 1) == ' ' || *(foldedSpace - 1) == '\t')
-        foldedSpace--;
+      // Add a single folding space if necessary.
+      if (*(bufWrite - 1) != ' ' && *(bufWrite - 1) != '\t')
+        *(bufWrite++) = ' ';
 
-      // put a single folded space character
-      *(foldedSpace - writeOffset) = ' ';
-      writeOffset += (buf - foldedSpace);
-      buf++;
+      // Skip CRLF, CR+space or LF+space ...
+      buf += 2;
 
-      // eliminate any additional white space
-      while (buf < buf_end &&
-              (*buf == '\n' || *buf == '\r' || *buf == ' ' || *buf == '\t'))
-      {
+      // ... and skip leading spaces in that line.
+      while (buf < buf_end && (*buf == ' ' || *buf == '\t'))
         buf++;
-        writeOffset++;
-      }
 
       // If we get here, the message headers ended in an empty line, like:
       // To: blah blah blah<CR><LF>  <CR><LF>[end of buffer]. The code below
       // requires buf to land on a newline to properly null-terminate the
       // string, so back up a tad so that it is pointing to one.
       if (buf == buf_end)
       {
         --buf;
@@ -1118,27 +1116,27 @@ SEARCH_NEWLINE:
       }
       goto SEARCH_NEWLINE;
     }
 
     if (header)
     {
       value = colon + 1;
       // eliminate trailing blanks after the colon
-      while (value < (buf - writeOffset) && (*value == ' ' || *value == '\t'))
+      while (value < bufWrite && (*value == ' ' || *value == '\t'))
         value++;
 
       header->value = value;
-      header->length = buf - header->value - writeOffset;
+      header->length = bufWrite - value;
       if (header->length < 0)
         header->length = 0;
     }
     if (*buf == '\r' || *buf == '\n')
     {
-      char *last = buf - writeOffset;
+      char *last = bufWrite;
       char *saveBuf = buf;
       if (*buf == '\r' && buf + 1 < buf_end && buf[1] == '\n')
         buf++;
       buf++;
       // null terminate the left-over slop so we don't confuse msg filters.
       *saveBuf = 0;
       *last = 0;  /* short-circuit const, and null-terminate header. */
     }