Bug 103870 - Fix some unsafe realloc usage in mailnews. r=Neil
authoraceman <acelists@atlas.sk>
Thu, 11 Jul 2013 11:31:55 -0400
changeset 12518 67f97998db4722025dee23a2be04cdcdf48a056c
parent 12517 65c5bfb05484d04ba58d906559a0177de392740c
child 12519 4520686e4809dec730be84ce7c7e276ebbe64254
push id1000
push userbugzilla@standard8.plus.com
push dateMon, 16 Sep 2013 20:21:48 +0000
treeherdercomm-esr52@5d0fb1691835 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersNeil
bugs103870
Bug 103870 - Fix some unsafe realloc usage in mailnews. r=Neil
mailnews/addrbook/src/nsVCard.cpp
mailnews/addrbook/src/nsVCardObj.cpp
mailnews/base/src/nsMsgDBView.h
mailnews/base/util/nsMsgLineBuffer.cpp
mailnews/base/util/nsMsgLineBuffer.h
mailnews/base/util/nsMsgUtils.cpp
mailnews/compose/src/nsMsgCompUtils.cpp
mailnews/compose/src/nsMsgSendLater.cpp
mailnews/imap/src/nsImapMailFolder.cpp
mailnews/local/public/nsIPop3Sink.idl
mailnews/local/src/nsParseMailbox.cpp
mailnews/local/src/nsParseMailbox.h
mailnews/local/src/nsPop3Protocol.cpp
mailnews/local/src/nsPop3Sink.cpp
mailnews/local/src/nsPop3Sink.h
--- a/mailnews/addrbook/src/nsVCard.cpp
+++ b/mailnews/addrbook/src/nsVCard.cpp
@@ -867,18 +867,18 @@ static void finiLex() {
  */
 static char * lexGetDataFromBase64()
     {
     unsigned long bytesLen = 0, bytesMax = 0;
     int quadIx = 0, pad = 0;
     unsigned long trip = 0;
     unsigned char b;
     int c;
-    unsigned char *bytes = NULL;
-    unsigned char *oldBytes = NULL;
+    unsigned char *bytes = nullptr;
+    unsigned char *oldBytes = nullptr;
 
     DBG_(("db: lexGetDataFromBase64\n"));
     while (1) {
 	c = lexGetc();
 	if (c == '\n') {
 	    ++mime_lineNum;
 	    if (lexLookahead() == '\n') {
 		/* a '\n' character by itself means end of data */
@@ -929,28 +929,26 @@ static char * lexGetDataFromBase64()
 		for (i = 0; i < 3; i++) {
 		    outBytes[2-i] = (unsigned char)(trip & 0xFF);
 		    trip >>= 8;
 		    }
 		numOut = 3 - pad;
 		if (bytesLen + numOut > bytesMax) {
 		    if (!bytes) {
 			bytesMax = 1024;
-			bytes = (unsigned char*)PR_CALLOC(bytesMax);
-			}
-		    else {
+		    } else {
 			bytesMax <<= 2;
 			oldBytes = bytes;
-			bytes = (unsigned char*)PR_Realloc(bytes,bytesMax);
-			}
-			if (bytes == 0) {
-			  mime_error("out of memory while processing BASE64 data\n");
-                          break;
-			}
 		    }
+		    bytes = (unsigned char*) PR_Realloc(oldBytes, bytesMax);
+		    if (!bytes) {
+			mime_error("out of memory while processing BASE64 data\n");
+			break;
+		    }
+		}
 		if (bytes) {
 			memcpy(bytes + bytesLen, outBytes, numOut);
 			bytesLen += numOut;
 		}
 		trip = 0;
 		quadIx = 0;
         pad = 0;
 		}
--- a/mailnews/addrbook/src/nsVCardObj.cpp
+++ b/mailnews/addrbook/src/nsVCardObj.cpp
@@ -858,18 +858,21 @@ static void appendcOFile_(OFile *fp, cha
 stuff:
   if (fp->len+1 < fp->limit) {
     fp->s[fp->len] = c;
     fp->len++;
     return;
   }
   else if (fp->alloc) {
     fp->limit = fp->limit + OFILE_REALLOC_SIZE;
-    fp->s = (char *)PR_Realloc(fp->s,fp->limit);
-    if (fp->s) goto stuff;
+    char* newBuf = (char *) PR_Realloc(fp->s, fp->limit);
+    if (newBuf) {
+      fp->s = newBuf;
+      goto stuff;
+    }
   }
   if (fp->alloc)
     PR_FREEIF(fp->s);
   fp->s = 0;
   fp->fail = 1;
 }
 
 static void appendcOFile(OFile *fp, char c)
--- a/mailnews/base/src/nsMsgDBView.h
+++ b/mailnews/base/src/nsMsgDBView.h
@@ -6,17 +6,16 @@
 #ifndef _nsMsgDBView_H_
 #define _nsMsgDBView_H_
 
 #include "nsIMsgDBView.h"
 #include "nsIMsgWindow.h"
 #include "nsIMessenger.h"
 #include "nsIMsgDatabase.h"
 #include "nsIMsgHdr.h"
-#include "nsMsgLineBuffer.h" // for nsByteArray
 #include "MailNewsTypes.h"
 #include "nsTArray.h"
 #include "nsIDBChangeListener.h"
 #include "nsITreeView.h"
 #include "nsITreeBoxObject.h"
 #include "nsITreeSelection.h"
 #include "nsIMsgFolder.h"
 #include "nsIDateTimeFormat.h"
--- a/mailnews/base/util/nsMsgLineBuffer.cpp
+++ b/mailnews/base/util/nsMsgLineBuffer.cpp
@@ -173,17 +173,17 @@ nsresult nsMsgLineBuffer::BufferInput(co
         
         net_buffer_size -= (newline - net_buffer);
         net_buffer = newline;
         m_bufferPos = 0;
     }
     return NS_OK;
 }
 
-nsresult nsMsgLineBuffer::HandleLine(char *line, uint32_t line_length)
+nsresult nsMsgLineBuffer::HandleLine(const char *line, uint32_t line_length)
 {
   NS_ASSERTION(false, "must override this method if you don't provide a handler");
   return NS_OK;
 }
 
 nsresult nsMsgLineBuffer::ConvertAndSendBuffer()
 {
     /* Convert the line terminator to the native form.
@@ -270,19 +270,19 @@ nsMsgLineStreamBuffer::nsMsgLineStreamBu
 nsMsgLineStreamBuffer::~nsMsgLineStreamBuffer()
 {
   PR_FREEIF(m_dataBuffer); // release our buffer...
 }
 
 
 nsresult nsMsgLineStreamBuffer::GrowBuffer(int32_t desiredSize)
 {
-  m_dataBuffer = (char *) PR_REALLOC(m_dataBuffer, desiredSize);
-  if (!m_dataBuffer)
-    return NS_ERROR_OUT_OF_MEMORY;
+  char* newBuffer = (char *) PR_REALLOC(m_dataBuffer, desiredSize);
+  NS_ENSURE_TRUE(newBuffer, NS_ERROR_OUT_OF_MEMORY);
+  m_dataBuffer = newBuffer;
   m_dataBufferSize = desiredSize;
   return NS_OK;
 }
 
 void nsMsgLineStreamBuffer::ClearBuffer()
 {
   m_startPos = 0;
   m_numBytesInBuffer = 0;
--- a/mailnews/base/util/nsMsgLineBuffer.h
+++ b/mailnews/base/util/nsMsgLineBuffer.h
@@ -28,30 +28,30 @@ protected:
   uint32_t  m_bufferSize;
   uint32_t  m_bufferPos;  // write Pos in m_buffer - where the next byte should go.
 };
 
 
 class NS_MSG_BASE nsMsgLineBufferHandler : public nsByteArray
 {
 public:
-  virtual nsresult HandleLine(char *line, uint32_t line_length) = 0;
+  virtual nsresult HandleLine(const char *line, uint32_t line_length) = 0;
 };
 
 class NS_MSG_BASE nsMsgLineBuffer : public nsMsgLineBufferHandler
 {
 public:
   nsMsgLineBuffer(nsMsgLineBufferHandler *handler, bool convertNewlinesP);
   
   virtual    ~nsMsgLineBuffer();
   nsresult    BufferInput(const char *net_buffer, int32_t net_buffer_size);
   // Not sure why anyone cares, by NNTPHost seems to want to know the buf pos.
   uint32_t    GetBufferPos() {return m_bufferPos;}
   
-  virtual nsresult HandleLine(char *line, uint32_t line_length);
+  virtual nsresult HandleLine(const char *line, uint32_t line_length);
   // flush last line, though it won't be CRLF terminated.
   virtual nsresult FlushLastLine();
 protected:
   nsMsgLineBuffer(bool convertNewlinesP);
   
   nsresult ConvertAndSendBuffer();
   void SetLookingForCRLF(bool b);
   
--- a/mailnews/base/util/nsMsgUtils.cpp
+++ b/mailnews/base/util/nsMsgUtils.cpp
@@ -615,17 +615,16 @@ nsresult NS_MsgCreatePathStringFromFolde
 #else
   return nsMsgI18NConvertFromUnicode(nsMsgI18NFileSystemCharset(), path, aPathCString);
 #endif
 }
 
 bool NS_MsgStripRE(const char **stringP, uint32_t *lengthP, char **modifiedSubject)
 {
   const char *s, *s_end;
-  const char *last;
   uint32_t L;
   bool result = false;
   NS_ASSERTION(stringP, "bad null param");
   if (!stringP) return false;
 
   // get localizedRe pref
   nsresult rv;
   nsString utf16LocalizedRe;
@@ -653,17 +652,16 @@ bool NS_MsgStripRE(const char **stringP,
       rv = mimeConverter->DecodeMimeHeaderToUTF8(nsDependentCString(*stringP),
         nullptr, false, true, decodedString);
   }
 
   s = !decodedString.IsEmpty() ? decodedString.get() : *stringP;
   L = lengthP ? *lengthP : strlen(s);
 
   s_end = s + L;
-  last = s;
 
  AGAIN:
 
   while (s < s_end && IS_SPACE(*s))
   s++;
 
   const char *tokPtr = checkString.get();
   while (*tokPtr)
@@ -761,38 +759,30 @@ char * NS_MsgSACopy (char **destination,
     if (*destination == nullptr)
       return(nullptr);
 
     PL_strcpy (*destination, source);
   }
   return *destination;
 }
 
-/*  Again like strdup but it concatinates and free's and uses Realloc
+/*  Again like strdup but it concatenates and free's and uses Realloc.
 */
 char * NS_MsgSACat (char **destination, const char *source)
 {
   if (source && *source)
-    if (*destination)
-    {
-      int length = PL_strlen (*destination);
-      *destination = (char *) PR_Realloc (*destination, length + PL_strlen(source) + 1);
-      if (*destination == nullptr)
-        return(nullptr);
+  {
+    int destLength = *destination ? PL_strlen(*destination) : 0;
+    char* newDestination = (char*) PR_Realloc(*destination, destLength + PL_strlen(source) + 1);
+    if (newDestination == nullptr)
+      return nullptr;
 
-      PL_strcpy (*destination + length, source);
-    }
-    else
-    {
-      *destination = (char *) PR_Malloc (PL_strlen(source) + 1);
-      if (*destination == nullptr)
-        return(nullptr);
-
-      PL_strcpy (*destination, source);
-    }
+    *destination = newDestination;
+    PL_strcpy(*destination + destLength, source);
+  }
   return *destination;
 }
 
 nsresult NS_MsgEscapeEncodeURLPath(const nsAString& aStr, nsCString& aResult)
 {
   return MsgEscapeString(NS_ConvertUTF16toUTF8(aStr), nsINetUtil::ESCAPE_URL_PATH, aResult);
 }
 
--- a/mailnews/compose/src/nsMsgCompUtils.cpp
+++ b/mailnews/compose/src/nsMsgCompUtils.cpp
@@ -275,17 +275,17 @@ mime_generate_headers (nsMsgCompFields *
   nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
   if (NS_FAILED(rv)) {
     *status = rv;
     return nullptr;
   }
 
   bool usemime = nsMsgMIMEGetConformToStandard();
   int32_t size = 0;
-  char *buffer = 0, *buffer_tail = 0;
+  char *buffer = nullptr, *buffer_tail = nullptr;
   bool isDraft =
     deliver_mode == nsIMsgSend::nsMsgSaveAsDraft ||
     deliver_mode == nsIMsgSend::nsMsgSaveAsTemplate ||
     deliver_mode == nsIMsgSend::nsMsgQueueForLater ||
     deliver_mode == nsIMsgSend::nsMsgDeliverBackground;
 
   const char* pFrom;
   const char* pTo;
@@ -302,19 +302,20 @@ mime_generate_headers (nsMsgCompFields *
   char *convbuf;
 
   bool hasDisclosedRecipient = false;
 
   nsAutoCString headerBuf;    // accumulate header strings to get length
   headerBuf.Truncate();
 
   NS_ASSERTION (fields, "null fields");
-  if (!fields)
+  if (!fields) {
+    *status = NS_ERROR_NULL_POINTER;
     return nullptr;
-
+  }
   pFrom = fields->GetFrom();
   if (pFrom)
     headerBuf.Append(pFrom);
   pReplyTo =fields->GetReplyTo();
   if (pReplyTo)
     headerBuf.Append(pReplyTo);
   pTo = fields->GetTo();
   if (pTo)
@@ -338,18 +339,20 @@ mime_generate_headers (nsMsgCompFields *
   /* Multiply by 3 here to make enough room for MimePartII conversion */
   size += 3 * headerBuf.Length();
 
   /* Add a bunch of slop for the static parts of the headers. */
   /* size += 2048; */
   size += 2560;
 
   buffer = (char *) PR_Malloc (size);
-  if (!buffer)
+  if (!buffer) {
+    *status = NS_ERROR_OUT_OF_MEMORY;
     return nullptr; /* NS_ERROR_OUT_OF_MEMORY */
+  }
 
   buffer_tail = buffer;
 
   if (pMessageID && *pMessageID) {
     PUSH_STRING ("Message-ID: ");
     PUSH_STRING (pMessageID);
     PUSH_NEWLINE ();
     /* MDN request header requires to have MessageID header presented
@@ -477,16 +480,17 @@ mime_generate_headers (nsMsgCompFields *
   PUSH_STRING ("MIME-Version: 1.0" CRLF);
 
   if (pNewsGrp && *pNewsGrp) {
     /* turn whitespace into a comma list
     */
     char *duppedNewsGrp = PL_strdup(pNewsGrp);
     if (!duppedNewsGrp) {
       PR_FREEIF(buffer);
+      *status = NS_ERROR_OUT_OF_MEMORY;
       return nullptr; /* NS_ERROR_OUT_OF_MEMORY */
     }
     char *n2 = nsMsgStripLine(duppedNewsGrp);
 
     for(char *ptr = n2; *ptr != '\0'; ptr++) {
       /* find first non white space */
       while(!IS_SPACE(*ptr) && *ptr != ',' && *ptr != '\0')
         ptr++;
@@ -510,17 +514,17 @@ mime_generate_headers (nsMsgCompFields *
     // to write to the outgoing message. In ANY case, we need to write the
     // "Newsgroup" header which is the "proper" header as opposed to the
     // HEADER_X_MOZILLA_NEWSHOST which can contain the "news:" URL's.
     //
     // Since n2 can contain data in the form of:
     // "news://news.mozilla.org/netscape.test,news://news.mozilla.org/netscape.junk"
     // we need to turn that into: "netscape.test,netscape.junk"
     //
-    nsCOMPtr <nsINntpService> nntpService = do_GetService("@mozilla.org/messenger/nntpservice;1");
+    nsCOMPtr<nsINntpService> nntpService = do_GetService("@mozilla.org/messenger/nntpservice;1", &rv);
     if (NS_FAILED(rv) || !nntpService) {
       *status = NS_ERROR_FAILURE;
       return nullptr;
     }
 
     nsCString newsgroupsHeaderVal;
     nsCString newshostHeaderVal;
     rv = nntpService->GenerateNewsHeaderValsForPosting(nsDependentCString(n2), getter_Copies(newsgroupsHeaderVal), getter_Copies(newshostHeaderVal));
@@ -702,23 +706,26 @@ mime_generate_headers (nsMsgCompFields *
   }
 
   if (pOtherHdr && *pOtherHdr) {
     /* Assume they already have the right newlines and continuations
      and so on.  for these headers, the PUSH_NEWLINE() happens in addressingWidgetOverlay.js */
     PUSH_STRING (pOtherHdr);
   }
 
-  if (buffer_tail > buffer + size - 1)
+  if (buffer_tail > buffer + size - 1) {
+    PR_FREEIF(buffer);
     return nullptr;
-
+  }
   /* realloc it smaller... */
-  buffer = (char*)PR_REALLOC (buffer, buffer_tail - buffer + 1);
+  char *newBuffer = (char*) PR_REALLOC(buffer, buffer_tail - buffer + 1);
+  if (!newBuffer) // The original bigger buffer is still usable to the caller.
+    return buffer;
 
-  return buffer;
+  return newBuffer;
 }
 
 static void
 GenerateGlobalRandomBytes(unsigned char *buf, int32_t len)
 {
   static bool      firstTime = true;
 
   if (firstTime)
--- a/mailnews/compose/src/nsMsgSendLater.cpp
+++ b/mailnews/compose/src/nsMsgSendLater.cpp
@@ -300,23 +300,22 @@ nsMsgSendLater::RebufferLeftovers(char *
   mLeftoverBuffer[aLen] = '\0';
   return NS_OK;
 }
 
 nsresult
 nsMsgSendLater::BuildNewBuffer(const char* aBuf, uint32_t aCount, uint32_t *totalBufSize)
 {
   // Only build a buffer when there are leftovers...
-  if (!mLeftoverBuffer)
-    return NS_ERROR_FAILURE;
+  NS_ENSURE_TRUE(mLeftoverBuffer, NS_ERROR_FAILURE);
 
   int32_t leftoverSize = PL_strlen(mLeftoverBuffer);
-  mLeftoverBuffer = (char *)PR_Realloc(mLeftoverBuffer, aCount + leftoverSize);
-  if (!mLeftoverBuffer)
-    return NS_ERROR_FAILURE;
+  char* newBuffer = (char *) PR_Realloc(mLeftoverBuffer, aCount + leftoverSize);
+  NS_ENSURE_TRUE(newBuffer, NS_ERROR_OUT_OF_MEMORY);
+  mLeftoverBuffer = newBuffer;
 
   memcpy(mLeftoverBuffer + leftoverSize, aBuf, aCount);
   *totalBufSize = aCount + leftoverSize;
   return NS_OK;
 }
 
 // Got data?
 NS_IMETHODIMP
--- a/mailnews/imap/src/nsImapMailFolder.cpp
+++ b/mailnews/imap/src/nsImapMailFolder.cpp
@@ -3243,18 +3243,19 @@ NS_IMETHODIMP nsImapMailFolder::CopyData
 {
   uint32_t readCount;
   uint32_t writeCount;
   if (!m_copyState)
     m_copyState = new nsImapMailCopyState();
 
   if ( aLength + m_copyState->m_leftOver > m_copyState->m_dataBufferSize )
   {
-    m_copyState->m_dataBuffer = (char *) PR_REALLOC(m_copyState->m_dataBuffer, aLength + m_copyState->m_leftOver+ 1);
-    NS_ENSURE_TRUE(m_copyState->m_dataBuffer, NS_ERROR_OUT_OF_MEMORY);
+    char *newBuffer = (char*) PR_REALLOC(m_copyState->m_dataBuffer, aLength + m_copyState->m_leftOver+ 1);
+    NS_ENSURE_TRUE(newBuffer, NS_ERROR_OUT_OF_MEMORY);
+    m_copyState->m_dataBuffer = newBuffer;
     m_copyState->m_dataBufferSize = aLength + m_copyState->m_leftOver;
   }
 
   char *start, *end;
   uint32_t linebreak_len = 1;
 
   nsresult rv = aIStream->Read(m_copyState->m_dataBuffer+m_copyState->m_leftOver, aLength, &readCount);
   if (NS_FAILED(rv))
--- a/mailnews/local/public/nsIPop3Sink.idl
+++ b/mailnews/local/public/nsIPop3Sink.idl
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "nsIPop3IncomingServer.idl"
 #include "nsIMsgFolder.idl"
 
 interface nsIURI;
 
-[scriptable, uuid(ceabfc6b-f139-4c25-890f-efb7c3069d3f)]
+[scriptable, uuid(ceabfc6b-f139-4c25-890f-efb7c3069d40)]
 interface nsIPop3Sink : nsISupports {
 
   attribute boolean userAuthenticated;
-  attribute string mailAccountURL;
+  attribute ACString mailAccountURL;
   attribute boolean buildMessageUri;
   attribute string messageUri;
   attribute string baseMessageUri;
 
   /// message uri for header-only message version
   attribute ACString origMessageUri;
 
   boolean BeginMailDelivery(in boolean uidlDownload, in nsIMsgWindow msgWindow);
--- a/mailnews/local/src/nsParseMailbox.cpp
+++ b/mailnews/local/src/nsParseMailbox.cpp
@@ -426,17 +426,17 @@ void nsMsgMailboxParser::AbortNewHeader(
 }
 
 void nsMsgMailboxParser::OnNewMessage(nsIMsgWindow *msgWindow)
 {
   PublishMsgHeader(msgWindow);
   Clear();
 }
 
-nsresult nsMsgMailboxParser::HandleLine(char *line, uint32_t lineLength)
+nsresult nsMsgMailboxParser::HandleLine(const char *line, uint32_t lineLength)
 {
   /* If this is the very first line of a non-empty folder, make sure it's an envelope */
   if (m_graph_progress_received == 0)
   {
     /* This is the first block from the file.  Check to see if this
        looks like a mail file. */
     const char *s = line;
     const char *end = s + lineLength;
--- a/mailnews/local/src/nsParseMailbox.h
+++ b/mailnews/local/src/nsParseMailbox.h
@@ -159,17 +159,17 @@ public:
 
   // message socket libnet callbacks, which come through folder pane
   nsresult ProcessMailboxInputStream(nsIURI* aURL, nsIInputStream *aIStream, uint32_t aLength);
 
   virtual void  DoneParsingFolder(nsresult status);
   virtual void  AbortNewHeader();
 
   // for nsMsgLineBuffer
-  virtual nsresult HandleLine(char *line, uint32_t line_length);
+  virtual nsresult HandleLine(const char *line, uint32_t line_length);
 
   void  UpdateDBFolderInfo();
   void  UpdateDBFolderInfo(nsIMsgDatabase *mailDB);
   void  UpdateStatusText(const char* stringName);
 
   // Update the progress bar based on what we know.
   virtual void    UpdateProgressPercent ();
   virtual void OnNewMessage(nsIMsgWindow *msgWindow);
--- a/mailnews/local/src/nsPop3Protocol.cpp
+++ b/mailnews/local/src/nsPop3Protocol.cpp
@@ -1868,20 +1868,16 @@ int32_t nsPop3Protocol::NextAuthStep()
                which causes the prompt to be different that time (to indicate
                that the old password was bogus.)
 
                But if we're just checking for new mail (biff) then don't bother
                prompting the user for a password: just fail silently.
             */
             SetFlag(POP3_PASSWORD_FAILED);
             Error("pop3PasswordFailure");
-
-            if (m_nsIPop3Sink)
-                m_nsIPop3Sink->SetMailAccountURL(NULL);
-
             return 0;
         }
         PR_LOG(POP3LOGMODULE, PR_LOG_DEBUG,
            ("still have some auth methods to try"));
 
         // TODO needed?
         //m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
 
@@ -2371,17 +2367,17 @@ int32_t
 nsPop3Protocol::GurlResponse()
 {
     ClearCapFlag(POP3_GURL_UNDEFINED);
 
     if (m_pop3ConData->command_succeeded)
     {
         SetCapFlag(POP3_HAS_GURL);
         if (m_nsIPop3Sink)
-            m_nsIPop3Sink->SetMailAccountURL(m_commandResponse.get());
+            m_nsIPop3Sink->SetMailAccountURL(m_commandResponse);
     }
     else
     {
         ClearCapFlag(POP3_HAS_GURL);
     }
     m_pop3Server->SetPop3CapabilityFlags(m_pop3ConData->capability_flags);
     m_pop3ConData->next_state = POP3_SEND_QUIT;
 
--- a/mailnews/local/src/nsPop3Sink.cpp
+++ b/mailnews/local/src/nsPop3Sink.cpp
@@ -45,38 +45,30 @@
 extern PRLogModuleInfo *POP3LOGMODULE;
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(nsPop3Sink, nsIPop3Sink)
 
 nsPop3Sink::nsPop3Sink()
 {
     m_authed = false;
     m_downloadingToTempFile = false;
-    m_accountUrl = nullptr;
     m_biffState = 0;
     m_numNewMessages = 0;
     m_numNewMessagesInFolder = 0;
     m_numMsgsDownloaded = 0;
     m_senderAuthed = false;
-    m_outputBuffer = nullptr;
-    m_outputBufferSize = 0;
-    m_popServer = nullptr;
     m_outFileStream = nullptr;
     m_uidlDownload = false;
     m_buildMessageUri = false;
     if (!POP3LOGMODULE)
       POP3LOGMODULE = PR_NewLogModule("POP3");
-
 }
 
 nsPop3Sink::~nsPop3Sink()
 {
-    PR_Free(m_accountUrl);
-    PR_Free(m_outputBuffer);
-    NS_IF_RELEASE(m_popServer);
     PR_LOG(POP3LOGMODULE, PR_LOG_MAX, ("Calling ReleaseFolderLock from ~nsPop3Sink"));
     ReleaseFolderLock();
 }
 
 nsresult
 nsPop3Sink::SetUserAuthenticated(bool authed)
 {
   m_authed = authed;
@@ -93,35 +85,26 @@ nsPop3Sink::GetUserAuthenticated(bool* a
 nsresult
 nsPop3Sink::SetSenderAuthedFlag(void* closure, bool authed)
 {
   m_authed = authed;
   return NS_OK;
 }
 
 nsresult
-nsPop3Sink::SetMailAccountURL(const char* urlString)
+nsPop3Sink::SetMailAccountURL(const nsACString &urlString)
 {
-  if (urlString)
-  {
-    PR_Free(m_accountUrl);
-    m_accountUrl = PL_strdup(urlString);
-  }
-
+  m_accountUrl.Assign(urlString);
   return NS_OK;
 }
 
 nsresult
-nsPop3Sink::GetMailAccountURL(char* *urlString)
+nsPop3Sink::GetMailAccountURL(nsACString &urlString)
 {
-  NS_ASSERTION(urlString, "null getter in getMailAccountURL");
-  if (!urlString)
-    return NS_ERROR_NULL_POINTER;
-
-  *urlString = strdup(m_accountUrl);
+  urlString.Assign(m_accountUrl);
   return NS_OK;
 }
 
 partialRecord::partialRecord() :
   m_msgDBHdr(nullptr)
 {
 }
 
@@ -560,58 +543,58 @@ nsPop3Sink::IncorporateBegin(const char*
       int64_t fileSize;
       path->GetFileSize(&fileSize);
       m_newMailParser->SetEnvelopePos((uint32_t) fileSize);
     }
   }
     if (closure)
         *closure = (void*) this;
 
-    char *dummyEnvelope = GetDummyEnvelope();
-
-  rv = WriteLineToMailbox(dummyEnvelope);
-  NS_ENSURE_SUCCESS(rv, rv);
-    // write out account-key before UIDL so the code that looks for
+    nsCString outputString(GetDummyEnvelope());
+    rv = WriteLineToMailbox(outputString);
+    NS_ENSURE_SUCCESS(rv, rv);
+    // Write out account-key before UIDL so the code that looks for
     // UIDL will find the account first and know it can stop looking
     // once it finds the UIDL line.
     if (!m_accountKey.IsEmpty())
     {
-      nsAutoCString outputString;
       outputString.AssignLiteral(HEADER_X_MOZILLA_ACCOUNT_KEY ": ");
       outputString.Append(m_accountKey);
       outputString.AppendLiteral(MSG_LINEBREAK);
-      WriteLineToMailbox(outputString.get());
+      rv = WriteLineToMailbox(outputString);
+      NS_ENSURE_SUCCESS(rv, rv);
     }
     if (uidlString)
     {
-      nsAutoCString uidlCString("X-UIDL: ");
-      uidlCString += uidlString;
-      uidlCString += MSG_LINEBREAK;
-      rv = WriteLineToMailbox(const_cast<char*>(uidlCString.get()));
+      outputString.AssignLiteral("X-UIDL: ");
+      outputString.Append(uidlString);
+      outputString.AppendLiteral(MSG_LINEBREAK);
+      rv = WriteLineToMailbox(outputString);
       NS_ENSURE_SUCCESS(rv, rv);
     }
+
     // WriteLineToMailbox("X-Mozilla-Status: 8000" MSG_LINEBREAK);
     char *statusLine = PR_smprintf(X_MOZILLA_STATUS_FORMAT MSG_LINEBREAK, flags);
-    rv = WriteLineToMailbox(statusLine);
-    if (NS_FAILED(rv)) return rv;
-    rv = WriteLineToMailbox("X-Mozilla-Status2: 00000000" MSG_LINEBREAK);
-    if (NS_FAILED(rv)) return rv;
+    outputString.Assign(statusLine);
+    rv = WriteLineToMailbox(outputString);
+    PR_smprintf_free(statusLine);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = WriteLineToMailbox(NS_LITERAL_CSTRING("X-Mozilla-Status2: 00000000" MSG_LINEBREAK));
+    NS_ENSURE_SUCCESS(rv, rv);
+
     // leave space for 60 bytes worth of keys/tags
-    rv = WriteLineToMailbox(X_MOZILLA_KEYWORDS);
-    PR_smprintf_free(statusLine);
+    rv = WriteLineToMailbox(NS_LITERAL_CSTRING(X_MOZILLA_KEYWORDS));
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPop3Sink::SetPopServer(nsIPop3IncomingServer *server)
 {
-  NS_IF_RELEASE(m_popServer);
-  m_popServer=server;
-  NS_ADDREF(m_popServer);
-
+  m_popServer = server;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPop3Sink::GetPopServer(nsIPop3IncomingServer **aServer)
 {
   NS_ENSURE_ARG_POINTER(aServer);
   NS_IF_ADDREF(*aServer = m_popServer);
@@ -629,18 +612,18 @@ NS_IMETHODIMP nsPop3Sink::SetFolder(nsIM
 {
   m_folder = aFolder;
   return NS_OK;
 }
 
 nsresult
 nsPop3Sink::GetServerFolder(nsIMsgFolder **aFolder)
 {
-  if (!aFolder)
-    return NS_ERROR_NULL_POINTER;
+  NS_ENSURE_ARG_POINTER(aFolder);
+
   if (m_popServer)
   {
     // not sure what this is used for - might be wrong if we have a deferred account.
     nsCOMPtr <nsIMsgIncomingServer> incomingServer = do_QueryInterface(m_popServer);
     if (incomingServer)
       return incomingServer->GetRootFolder(aFolder);
   }
   *aFolder = nullptr;
@@ -673,63 +656,43 @@ nsPop3Sink::GetDummyEnvelope(void)
   PL_strcpy(result + 7 + 24, MSG_LINEBREAK);
   return result;
 }
 
 nsresult
 nsPop3Sink::IncorporateWrite(const char* block,
                              int32_t length)
 {
-  int32_t blockOffset = 0;
+  m_outputBuffer.Truncate();
   if (!strncmp(block, "From ", 5))
-  {
-    length++;
-    blockOffset = 1;
-  }
-  if (!m_outputBuffer || length > m_outputBufferSize)
-  {
-    if (!m_outputBuffer)
-      m_outputBuffer = (char*) PR_MALLOC(length+1);
-    else
-      m_outputBuffer = (char*) PR_REALLOC(m_outputBuffer, length+1);
+    m_outputBuffer.Assign('>');
 
-    m_outputBufferSize = length;
-  }
-  if (m_outputBuffer)
-  {
-    if (blockOffset == 1)
-      *m_outputBuffer = '>';
-    memcpy(m_outputBuffer + blockOffset, block, length - blockOffset);
-    *(m_outputBuffer + length) = 0;
-    nsresult rv = WriteLineToMailbox (m_outputBuffer);
-    if (NS_FAILED(rv)) return rv;
-  }
-  return NS_OK;
+  m_outputBuffer.Append(block);
+
+  return WriteLineToMailbox(m_outputBuffer);
 }
 
-nsresult nsPop3Sink::WriteLineToMailbox(const char *buffer)
+nsresult nsPop3Sink::WriteLineToMailbox(const nsACString& buffer)
 {
-
-  if (buffer)
+  if (!buffer.IsEmpty())
   {
-    int32_t bufferLen = PL_strlen(buffer);
-    if (m_newMailParser) // HandleLine should really take a const char *...
-      m_newMailParser->HandleLine((char *) buffer, bufferLen);
+    uint32_t bufferLen = buffer.Length();
+    if (m_newMailParser)
+      m_newMailParser->HandleLine(buffer.BeginReading(), bufferLen);
     // The following (!m_outFileStream etc) was added to make sure that we don't write somewhere
     // where for some reason or another we can't write to and lose the messages
     // See bug 62480
-    if (!m_outFileStream)
-      return NS_ERROR_OUT_OF_MEMORY;
+    NS_ENSURE_TRUE(m_outFileStream, NS_ERROR_OUT_OF_MEMORY);
 
     // seek to the end in case someone else has seeked elsewhere in our stream.
     nsCOMPtr <nsISeekableStream> seekableOutStream = do_QueryInterface(m_outFileStream);
     seekableOutStream->Seek(nsISeekableStream::NS_SEEK_END, 0);
     uint32_t bytesWritten;
-    m_outFileStream->Write(buffer, bufferLen, &bytesWritten);
-    if ((int32_t) bytesWritten != bufferLen) return NS_ERROR_FAILURE;
+    m_outFileStream->Write(buffer.BeginReading(), bufferLen, &bytesWritten);
+    NS_ENSURE_TRUE(bytesWritten == bufferLen, NS_ERROR_FAILURE);
   }
   return NS_OK;
 }
 
 nsresult nsPop3Sink::HandleTempDownloadFailed(nsIMsgWindow *msgWindow)
 {
   nsresult rv;
   nsCOMPtr<nsIStringBundleService> bundleService =
@@ -781,17 +744,17 @@ nsPop3Sink::IncorporateComplete(nsIMsgWi
       m_newMailParser->m_newMsgHdr)
   {
     uint32_t msgKey;
     m_newMailParser->m_newMsgHdr->GetMessageKey(&msgKey);
     m_messageUri.Truncate();
     nsBuildLocalMessageURI(m_baseMessageUri.get(), msgKey, m_messageUri);
   }
 
-  nsresult rv = WriteLineToMailbox(MSG_LINEBREAK);
+  nsresult rv = WriteLineToMailbox(NS_LITERAL_CSTRING(MSG_LINEBREAK));
   NS_ENSURE_SUCCESS(rv, rv);
   bool leaveOnServer = false;
   m_popServer->GetLeaveMessagesOnServer(&leaveOnServer);
   // We need to flush the output stream, in case mail filters move
   // the new message, which relies on all the data being flushed.
   rv = m_outFileStream->Flush(); // Make sure the message is written to the disk
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ASSERTION(m_newMailParser, "could not get m_newMailParser");
--- a/mailnews/local/src/nsPop3Sink.h
+++ b/mailnews/local/src/nsPop3Sink.h
@@ -11,16 +11,17 @@
 #include "nsIOutputStream.h"
 #include "prmem.h"
 #include "prio.h"
 #include "plstr.h"
 #include "prenv.h"
 #include "nsIMsgFolder.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
+#include "nsStringGlue.h"
 
 class nsParseNewMailState;
 class nsIMsgFolder;
 
 struct partialRecord
 {
   partialRecord();
   ~partialRecord();
@@ -39,31 +40,29 @@ public:
     NS_DECL_NSIPOP3SINK
     nsresult GetServerFolder(nsIMsgFolder **aFolder);
     nsresult FindPartialMessages();
     void CheckPartialMessages(nsIPop3Protocol *protocol);
 
     static char*  GetDummyEnvelope(void);
 
 protected:
-
-    nsresult WriteLineToMailbox(const char *buffer);
+    nsresult WriteLineToMailbox(const nsACString& buffer);
     nsresult ReleaseFolderLock();
     nsresult HandleTempDownloadFailed(nsIMsgWindow *msgWindow);
 
     bool m_authed;
-    char* m_accountUrl;
+    nsCString m_accountUrl;
     uint32_t m_biffState;
     int32_t m_numNewMessages;
     int32_t m_numNewMessagesInFolder;
     int32_t m_numMsgsDownloaded;
     bool m_senderAuthed;
-    char* m_outputBuffer;
-    int32_t m_outputBufferSize;
-    nsIPop3IncomingServer *m_popServer;
+    nsCString m_outputBuffer;
+    nsCOMPtr<nsIPop3IncomingServer> m_popServer;
     //Currently the folder we want to update about biff info
     nsCOMPtr<nsIMsgFolder> m_folder;
     nsRefPtr<nsParseNewMailState> m_newMailParser;
     nsCOMPtr <nsIOutputStream> m_outFileStream; // the file we write to, which may be temporary
     nsCOMPtr<nsIMsgPluggableStore> m_msgStore;
     nsCOMPtr <nsIOutputStream> m_inboxOutputStream; // the actual mailbox
     bool m_uidlDownload;
     bool m_buildMessageUri;