From abbb6cec3f7c85c76f2428474b80f559284a3a4d Mon Sep 17 00:00:00 2001 From: "tingley%sundell.net" Date: Tue, 9 Jul 2002 05:21:33 +0000 Subject: [PATCH] Fix for bug 153480 - crash deleting download manager entries. r=rjc sr=waterson git-svn-id: svn://10.0.0.236/trunk@124831 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/rdf/base/src/nsInMemoryDataSource.cpp | 51 ++++++++++++------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/mozilla/rdf/base/src/nsInMemoryDataSource.cpp b/mozilla/rdf/base/src/nsInMemoryDataSource.cpp index db6bd86e37f..267b0d8a096 100644 --- a/mozilla/rdf/base/src/nsInMemoryDataSource.cpp +++ b/mozilla/rdf/base/src/nsInMemoryDataSource.cpp @@ -765,27 +765,44 @@ InMemoryArcsEnumeratorImpl::HasMoreElements(PRBool* aResult) } } else - while (mAssertion) { - nsIRDFResource* next = mAssertion->u.as.mProperty; + while (mAssertion) { + nsIRDFResource* next = mAssertion->u.as.mProperty; - PRBool alreadyReturned = PR_FALSE; - for (PRInt32 i = mAlreadyReturned.Count() - 1; i >= 0; --i) { - if (mAlreadyReturned[i] == mCurrent) { - alreadyReturned = PR_TRUE; - break; + // "next" is the property arc we are tentatively going to return + // in a subsequent GetNext() call. It is important to do two + // things, however, before that can happen: + // 1) Make sure it's not an arc we've already returned. + // 2) Make sure that |mAssertion| is not left pointing to + // another assertion that has the same property as this one. + // The first is a practical concern; the second a defense against + // an obscure crash and other erratic behavior. To ensure the + // second condition, skip down the chain until we find the next + // assertion with a property that doesn't match the current one. + // (All these assertions would be skipped via mAlreadyReturned + // checks anyways; this is even a bit faster.) + + do { + mAssertion = (mSource ? mAssertion->mNext : + mAssertion->u.as.mInvNext); + } + while (mAssertion && (next == mAssertion->u.as.mProperty)); + + PRBool alreadyReturned = PR_FALSE; + for (PRInt32 i = mAlreadyReturned.Count() - 1; i >= 0; --i) { + if (mAlreadyReturned[i] == next) { + alreadyReturned = PR_TRUE; + break; + } + } + + if (! alreadyReturned) { + mCurrent = next; + NS_ADDREF(mCurrent); + *aResult = PR_TRUE; + return NS_OK; } } - mAssertion = (mSource ? mAssertion->mNext : mAssertion->u.as.mInvNext); - - if (! alreadyReturned) { - mCurrent = next; - NS_ADDREF(mCurrent); - *aResult = PR_TRUE; - return NS_OK; - } - } - *aResult = PR_FALSE; return NS_OK; }