Fix for bug 603844 (Leak txUnknownHandler+ with transformToDocument(textnode)). r=sicking.

This commit is contained in:
Peter Van der Beken 2010-12-02 11:12:27 -05:00
parent 70a155c558
commit 5b1dbd07be
15 changed files with 152 additions and 133 deletions

View File

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script>
function boom()
{
var frame = document.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
frame.onload = y;
frame.src = "data:text/plain,0";
document.body.appendChild(frame);
frameDoc = frame.contentDocument;
function y()
{
frameDoc.removeChild(frameDoc.documentElement);
var xp = new XSLTProcessor;
xp.importStylesheet(frameDoc);
try {
xp.transformToDocument(frameDoc.createTextNode('x'));
} catch(e) { }
document.documentElement.removeAttribute("class");
}
}
</script>
</head>
<body onload="boom();"></body>
</html>

View File

@ -11,4 +11,5 @@ load 528488.xml
load 528963.xml
load 545927.html
load 601543.html
load 603844.html
load 602115.html

View File

@ -408,122 +408,103 @@ txResultBuffer::addTransaction(txOutputTransaction* aTransaction)
return NS_OK;
}
struct Holder
static nsresult
flushTransaction(txOutputTransaction* aTransaction,
txAXMLEventHandler* aHandler,
nsAFlatString::const_char_iterator& aIter)
{
txAXMLEventHandler** mHandler;
nsresult mResult;
nsAFlatString::const_char_iterator mIter;
};
static PRBool
flushTransaction(txOutputTransaction* aElement, Holder* aData)
{
Holder* holder = aData;
txAXMLEventHandler* handler = *holder->mHandler;
txOutputTransaction* transaction = aElement;
nsresult rv;
switch (transaction->mType) {
switch (aTransaction->mType) {
case txOutputTransaction::eAttributeAtomTransaction:
{
txAttributeAtomTransaction* transaction =
static_cast<txAttributeAtomTransaction*>(aElement);
rv = handler->attribute(transaction->mPrefix,
transaction->mLocalName,
transaction->mLowercaseLocalName,
transaction->mNsID,
transaction->mValue);
break;
static_cast<txAttributeAtomTransaction*>(aTransaction);
return aHandler->attribute(transaction->mPrefix,
transaction->mLocalName,
transaction->mLowercaseLocalName,
transaction->mNsID,
transaction->mValue);
}
case txOutputTransaction::eAttributeTransaction:
{
txAttributeTransaction* attrTransaction =
static_cast<txAttributeTransaction*>(aElement);
rv = handler->attribute(attrTransaction->mPrefix,
attrTransaction->mLocalName,
attrTransaction->mNsID,
attrTransaction->mValue);
break;
static_cast<txAttributeTransaction*>(aTransaction);
return aHandler->attribute(attrTransaction->mPrefix,
attrTransaction->mLocalName,
attrTransaction->mNsID,
attrTransaction->mValue);
}
case txOutputTransaction::eCharacterTransaction:
case txOutputTransaction::eCharacterNoOETransaction:
{
txCharacterTransaction* charTransaction =
static_cast<txCharacterTransaction*>(aElement);
nsAFlatString::const_char_iterator& start =
holder->mIter;
static_cast<txCharacterTransaction*>(aTransaction);
nsAFlatString::const_char_iterator start = aIter;
nsAFlatString::const_char_iterator end =
start + charTransaction->mLength;
rv = handler->characters(Substring(start, end),
transaction->mType ==
txOutputTransaction::eCharacterNoOETransaction);
start = end;
break;
aIter = end;
return aHandler->characters(Substring(start, end),
aTransaction->mType ==
txOutputTransaction::eCharacterNoOETransaction);
}
case txOutputTransaction::eCommentTransaction:
{
txCommentTransaction* commentTransaction =
static_cast<txCommentTransaction*>(aElement);
rv = handler->comment(commentTransaction->mValue);
break;
static_cast<txCommentTransaction*>(aTransaction);
return aHandler->comment(commentTransaction->mValue);
}
case txOutputTransaction::eEndElementTransaction:
{
rv = handler->endElement();
break;
return aHandler->endElement();
}
case txOutputTransaction::ePITransaction:
{
txPITransaction* piTransaction =
static_cast<txPITransaction*>(aElement);
rv = handler->processingInstruction(piTransaction->mTarget,
piTransaction->mData);
break;
static_cast<txPITransaction*>(aTransaction);
return aHandler->processingInstruction(piTransaction->mTarget,
piTransaction->mData);
}
case txOutputTransaction::eStartDocumentTransaction:
{
rv = handler->startDocument();
break;
return aHandler->startDocument();
}
case txOutputTransaction::eStartElementAtomTransaction:
{
txStartElementAtomTransaction* transaction =
static_cast<txStartElementAtomTransaction*>(aElement);
rv = handler->startElement(transaction->mPrefix,
transaction->mLocalName,
transaction->mLowercaseLocalName,
transaction->mNsID);
break;
static_cast<txStartElementAtomTransaction*>(aTransaction);
return aHandler->startElement(transaction->mPrefix,
transaction->mLocalName,
transaction->mLowercaseLocalName,
transaction->mNsID);
}
case txOutputTransaction::eStartElementTransaction:
{
txStartElementTransaction* transaction =
static_cast<txStartElementTransaction*>(aElement);
rv = handler->startElement(transaction->mPrefix,
transaction->mLocalName,
transaction->mNsID);
break;
static_cast<txStartElementTransaction*>(aTransaction);
return aHandler->startElement(transaction->mPrefix,
transaction->mLocalName,
transaction->mNsID);
}
default:
{
NS_NOTREACHED("Unexpected transaction type");
}
}
holder->mResult = rv;
return NS_SUCCEEDED(rv);
return NS_ERROR_UNEXPECTED;
}
nsresult
txResultBuffer::flushToHandler(txAXMLEventHandler** aHandler)
txResultBuffer::flushToHandler(txAXMLEventHandler* aHandler)
{
Holder data = { aHandler, NS_OK };
mStringValue.BeginReading(data.mIter);
nsAFlatString::const_char_iterator iter;
mStringValue.BeginReading(iter);
for (PRUint32 i = 0, len = mTransactions.Length(); i < len; ++i) {
if (!flushTransaction(mTransactions[i], &data)) {
break;
}
nsresult rv = flushTransaction(mTransactions[i], aHandler, iter);
NS_ENSURE_SUCCESS(rv, rv);
}
return data.mResult;
return NS_OK;
}
txOutputTransaction*

View File

@ -56,12 +56,7 @@ public:
nsresult addTransaction(txOutputTransaction* aTransaction);
/**
* Flush the transactions to aHandler. Some handlers create a new handler
* and replace themselves with the new handler. The pointer that aHandler
* points to should be updated in that case.
*/
nsresult flushToHandler(txAXMLEventHandler** aHandler);
nsresult flushToHandler(txAXMLEventHandler* aHandler);
txOutputTransaction* getLastTransaction();

View File

@ -88,10 +88,7 @@ convertRtfToNode(txIEvalContext *aContext, txResultTreeFragment *aRtf)
txOutputFormat format;
txMozillaXMLOutput mozHandler(&format, domFragment, PR_TRUE);
txAXMLEventHandler* handler = &mozHandler;
rv = aRtf->flushToHandler(&handler);
NS_ASSERTION(handler == &mozHandler,
"This handler shouldn't have been replaced!");
rv = aRtf->flushToHandler(&mozHandler);
NS_ENSURE_SUCCESS(rv, rv);
rv = mozHandler.closePrevious(PR_TRUE);

View File

@ -429,7 +429,7 @@ txCopyOf::execute(txExecutionState& aEs)
txResultTreeFragment* rtf =
static_cast<txResultTreeFragment*>
(static_cast<txAExprResult*>(exprRes));
return rtf->flushToHandler(&aEs.mResultHandler);
return rtf->flushToHandler(aEs.mResultHandler);
}
default:
{

View File

@ -58,13 +58,10 @@
using namespace mozilla::dom;
txMozillaTextOutput::txMozillaTextOutput(nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument,
nsITransformObserver* aObserver)
txMozillaTextOutput::txMozillaTextOutput(nsITransformObserver* aObserver)
{
MOZ_COUNT_CTOR(txMozillaTextOutput);
mObserver = do_GetWeakReference(aObserver);
createResultDocument(aSourceDocument, aResultDocument);
}
txMozillaTextOutput::txMozillaTextOutput(nsIDOMDocumentFragment* aDest)

View File

@ -54,18 +54,17 @@ class nsIContent;
class txMozillaTextOutput : public txAOutputXMLEventHandler
{
public:
txMozillaTextOutput(nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument,
nsITransformObserver* aObserver);
txMozillaTextOutput(nsITransformObserver* aObserver);
txMozillaTextOutput(nsIDOMDocumentFragment* aDest);
virtual ~txMozillaTextOutput();
TX_DECL_TXAXMLEVENTHANDLER
TX_DECL_TXAOUTPUTXMLEVENTHANDLER
private:
nsresult createResultDocument(nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument);
private:
nsresult createXHTMLElement(nsIAtom* aName, nsIContent** aResult);
nsCOMPtr<nsIContent> mTextParent;

View File

@ -80,11 +80,7 @@ using namespace mozilla::dom;
if (!mCurrentNode) \
return NS_ERROR_UNEXPECTED
txMozillaXMLOutput::txMozillaXMLOutput(const nsSubstring& aRootName,
PRInt32 aRootNsID,
txOutputFormat* aFormat,
nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument,
txMozillaXMLOutput::txMozillaXMLOutput(txOutputFormat* aFormat,
nsITransformObserver* aObserver)
: mTreeDepth(0),
mBadChildLevel(0),
@ -104,8 +100,6 @@ txMozillaXMLOutput::txMozillaXMLOutput(const nsSubstring& aRootName,
mOutputFormat.merge(*aFormat);
mOutputFormat.setFromDefaults();
createResultDocument(aRootName, aRootNsID, aSourceDocument, aResultDocument);
}
txMozillaXMLOutput::txMozillaXMLOutput(txOutputFormat* aFormat,

View File

@ -93,11 +93,7 @@ private:
class txMozillaXMLOutput : public txAOutputXMLEventHandler
{
public:
txMozillaXMLOutput(const nsSubstring& aRootName,
PRInt32 aRootNsID,
txOutputFormat* aFormat,
nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument,
txMozillaXMLOutput(txOutputFormat* aFormat,
nsITransformObserver* aObserver);
txMozillaXMLOutput(txOutputFormat* aFormat,
nsIDOMDocumentFragment* aFragment,
@ -109,14 +105,15 @@ public:
nsresult closePrevious(PRBool aFlushText);
nsresult createResultDocument(const nsSubstring& aName, PRInt32 aNsID,
nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument);
private:
nsresult createTxWrapper();
nsresult startHTMLElement(nsIContent* aElement, PRBool aXHTML);
nsresult endHTMLElement(nsIContent* aElement);
void processHTTPEquiv(nsIAtom* aHeader, const nsString& aValue);
nsresult createResultDocument(const nsSubstring& aName, PRInt32 aNsID,
nsIDOMDocument* aSourceDocument,
nsIDOMDocument* aResultDocument);
nsresult createHTMLElement(nsIAtom* aName,
nsIContent** aResult);

View File

@ -121,28 +121,39 @@ txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
case eXMLOutput:
{
*aHandler = new txUnknownHandler(mEs);
break;
return NS_OK;
}
case eHTMLOutput:
{
*aHandler = new txMozillaXMLOutput(EmptyString(),
kNameSpaceID_None,
aFormat, mSourceDocument,
mResultDocument, mObserver);
break;
nsAutoPtr<txMozillaXMLOutput> handler(
new txMozillaXMLOutput(aFormat, mObserver));
nsresult rv = handler->createResultDocument(EmptyString(),
kNameSpaceID_None,
mSourceDocument,
mResultDocument);
if (NS_SUCCEEDED(rv)) {
*aHandler = handler.forget();
}
return rv;
}
case eTextOutput:
{
*aHandler = new txMozillaTextOutput(mSourceDocument,
mResultDocument,
mObserver);
break;
nsAutoPtr<txMozillaTextOutput> handler(
new txMozillaTextOutput(mObserver));
nsresult rv = handler->createResultDocument(mSourceDocument,
mResultDocument);
if (NS_SUCCEEDED(rv)) {
*aHandler = handler.forget();
}
return rv;
}
}
NS_ENSURE_TRUE(*aHandler, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
nsresult
@ -162,23 +173,33 @@ txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
case eXMLOutput:
case eHTMLOutput:
{
*aHandler = new txMozillaXMLOutput(aName, aNsID, aFormat,
mSourceDocument,
mResultDocument,
mObserver);
break;
nsAutoPtr<txMozillaXMLOutput> handler(
new txMozillaXMLOutput(aFormat, mObserver));
nsresult rv = handler->createResultDocument(aName, aNsID,
mSourceDocument,
mResultDocument);
if (NS_SUCCEEDED(rv)) {
*aHandler = handler.forget();
}
return rv;
}
case eTextOutput:
{
*aHandler = new txMozillaTextOutput(mSourceDocument,
mResultDocument,
mObserver);
break;
nsAutoPtr<txMozillaTextOutput> handler(
new txMozillaTextOutput(mObserver));
nsresult rv = handler->createResultDocument(mSourceDocument,
mResultDocument);
if (NS_SUCCEEDED(rv)) {
*aHandler = handler.forget();
}
return rv;
}
}
NS_ENSURE_TRUE(*aHandler, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
nsresult

View File

@ -80,7 +80,7 @@ double txResultTreeFragment::numberValue()
return Double::toDouble(mBuffer->mStringValue);
}
nsresult txResultTreeFragment::flushToHandler(txAXMLEventHandler** aHandler)
nsresult txResultTreeFragment::flushToHandler(txAXMLEventHandler* aHandler)
{
if (!mBuffer) {
return NS_ERROR_FAILURE;

View File

@ -51,7 +51,7 @@ public:
TX_DECL_EXPRRESULT
nsresult flushToHandler(txAXMLEventHandler** aHandler);
nsresult flushToHandler(txAXMLEventHandler* aHandler);
void setNode(const txXPathNode* aNode)
{

View File

@ -153,14 +153,17 @@ nsresult txUnknownHandler::createHandlerAndFlush(PRBool aHTMLRoot,
format.mMethod = aHTMLRoot ? eHTMLOutput : eXMLOutput;
}
txAXMLEventHandler *handler = nsnull;
nsAutoPtr<txAXMLEventHandler> handler;
nsresult rv = mEs->mOutputHandlerFactory->createHandlerWith(&format, aName,
aNsID,
&handler);
getter_Transfers(handler));
NS_ENSURE_SUCCESS(rv, rv);
rv = mBuffer->flushToHandler(handler);
NS_ENSURE_SUCCESS(rv, rv);
mEs->mOutputHandler = handler;
mEs->mResultHandler = handler;
mEs->mResultHandler = handler.forget();
return mBuffer->flushToHandler(&handler);
return NS_OK;
}

View File

@ -1576,8 +1576,10 @@ GCGraphBuilder::DescribeNode(CCNodeType type, nsrefcnt refCount,
}
if (type == RefCounted) {
if (refCount == 0 || refCount == PR_UINT32_MAX)
Fault("zero or overflowing refcount", mCurrPi);
if (refCount == 0)
Fault("zero refcount", mCurrPi);
if (refCount == PR_UINT32_MAX)
Fault("overflowing refcount", mCurrPi);
mCurrPi->mRefCount = refCount;
}