fix potential stack overflow in quick search w/ bad threading, r/sr=neil, bug 530044
authorDavid Bienvenu <bienvenu@nventure.com>
Wed, 16 Dec 2009 15:00:31 -0800
changeset 4543 27b6c6e10fd20051a9bfe62604eb0a7bd0dbf03a
parent 4542 1b450d1a4a84fd340c6463ff1e4b2f8fde8a4c77
child 4544 553dba4cb6a5e374c349b36deb6076f63c1b1d44
push idunknown
push userunknown
push dateunknown
bugs530044
fix potential stack overflow in quick search w/ bad threading, r/sr=neil, bug 530044
mailnews/base/src/nsMsgQuickSearchDBView.cpp
--- a/mailnews/base/src/nsMsgQuickSearchDBView.cpp
+++ b/mailnews/base/src/nsMsgQuickSearchDBView.cpp
@@ -637,30 +637,46 @@ nsMsgQuickSearchDBView::ListIdsInThreadO
                                              nsMsgKey parentKey, PRInt32 level,
                                              nsMsgKey keyToSkip,
                                              nsMsgViewIndex *viewIndex,
                                              PRUint32 *pNumListed)
 {
   nsCOMPtr <nsISimpleEnumerator> msgEnumerator;
   nsresult rv = threadHdr->EnumerateMessages(parentKey, getter_AddRefs(msgEnumerator));
   NS_ENSURE_SUCCESS(rv, rv);
+  
+  // We use the numChildren as a sanity check on the thread structure.
+  PRUint32 numChildren;
+  (void) threadHdr->GetNumChildren(&numChildren);
   PRBool hasMore;
   nsCOMPtr <nsISupports> supports;
   nsCOMPtr <nsIMsgDBHdr> msgHdr;
-  while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(rv = msgEnumerator->HasMoreElements(&hasMore)) && hasMore)
+  while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(rv = msgEnumerator->HasMoreElements(&hasMore)) &&
+         hasMore)
   {
     rv = msgEnumerator->GetNext(getter_AddRefs(supports));
     if (NS_SUCCEEDED(rv) && supports)
     {
       msgHdr = do_QueryInterface(supports);
       nsMsgKey msgKey;
       msgHdr->GetMessageKey(&msgKey);
       if (msgKey == keyToSkip)
         continue;
 
+      // If we discover depths of more than numChildren, it means we have
+      // some sort of circular thread relationship and we bail out of the
+      // while loop before overflowing the stack with recursive calls.
+      // Technically, this is an error, but forcing a database rebuild
+      // is too destructive so we just return.
+      if (*pNumListed > numChildren)
+      {
+        NS_ERROR("loop in message threading while listing children");
+        return NS_OK;
+      }
+
       PRInt32 childLevel = level;
       if (m_origKeys.BinaryIndexOf(msgKey) != -1)
       {
         PRUint32 msgFlags;
         msgHdr->GetFlags(&msgFlags);
         InsertMsgHdrAt(*viewIndex, msgHdr, msgKey, msgFlags & ~MSG_VIEW_FLAGS, level);
         (*pNumListed)++;
         (*viewIndex)++;