Make setting innerHTML in XHTML not crash on malformed content and throw an

exception instead.  Bug 272011, patch by steve.swanson@mackichan.com,
r+sr=bzbarsky
This commit is contained in:
bzbarsky%mit.edu 2004-12-04 17:51:12 +00:00
parent 8ace54dc3d
commit 6b0b8501f3
4 changed files with 53 additions and 30 deletions

View File

@ -2504,7 +2504,7 @@ nsRange::CreateContextualFragment(const nsAString& aFragment,
} }
if (NS_SUCCEEDED(result)) { if (NS_SUCCEEDED(result)) {
sink->GetFragment(aReturn); result = sink->GetFragment(aReturn);
} }
} }
} }

View File

@ -1338,15 +1338,6 @@ nsXMLContentSink::HandleXMLDeclaration(const PRUnichar *aData,
NS_IMETHODIMP NS_IMETHODIMP
nsXMLContentSink::ReportError(const PRUnichar* aErrorText, nsXMLContentSink::ReportError(const PRUnichar* aErrorText,
const PRUnichar* aSourceText) const PRUnichar* aSourceText)
{
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mDocument));
return ReportErrorFrom( aErrorText, aSourceText, node );
}
NS_IMETHODIMP
nsXMLContentSink::ReportErrorFrom(const PRUnichar* aErrorText,
const PRUnichar* aSourceText,
nsIDOMNode* aNode)
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
@ -1360,13 +1351,14 @@ nsXMLContentSink::ReportErrorFrom(const PRUnichar* aErrorText,
// Clear the current content and // Clear the current content and
// prepare to set <parsererror> as the document root // prepare to set <parsererror> as the document root
if (aNode) { nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mDocument));
if (node) {
for (;;) { for (;;) {
nsCOMPtr<nsIDOMNode> child, dummy; nsCOMPtr<nsIDOMNode> child, dummy;
aNode->GetLastChild(getter_AddRefs(child)); node->GetLastChild(getter_AddRefs(child));
if (!child) if (!child)
break; break;
aNode->RemoveChild(child, getter_AddRefs(dummy)); node->RemoveChild(child, getter_AddRefs(dummy));
} }
} }
NS_IF_RELEASE(mDocElement); NS_IF_RELEASE(mDocElement);

View File

@ -132,12 +132,6 @@ protected:
PRInt32 PushContent(nsIContent *aContent); PRInt32 PushContent(nsIContent *aContent);
already_AddRefed<nsIContent> PopContent(); already_AddRefed<nsIContent> PopContent();
// node is the base content which will be cleared out and an error fragment will be inserted
// return value indicates whether fragment was successfully created
NS_IMETHOD ReportErrorFrom(const PRUnichar* aErrorText,
const PRUnichar* aSourceText,
nsIDOMNode* aNode);
nsresult ProcessBASETag(nsIContent* aContent); nsresult ProcessBASETag(nsIContent* aContent);

View File

@ -48,7 +48,9 @@
#include "nsINodeInfo.h" #include "nsINodeInfo.h"
#include "nsNodeInfoManager.h" #include "nsNodeInfoManager.h"
#include "nsContentCreatorFunctions.h" #include "nsContentCreatorFunctions.h"
#include "nsDOMError.h"
#include "nsIConsoleService.h"
#include "nsServiceManagerUtils.h"
class nsXMLFragmentContentSink : public nsXMLContentSink, class nsXMLFragmentContentSink : public nsXMLContentSink,
public nsIFragmentContentSink public nsIFragmentContentSink
@ -107,9 +109,10 @@ protected:
nsCOMPtr<nsIDocument> mTargetDocument; nsCOMPtr<nsIDocument> mTargetDocument;
// the fragment // the fragment
nsCOMPtr<nsIContent> mRoot; nsCOMPtr<nsIContent> mRoot;
PRPackedBool mParseError;
// if FALSE, take content inside endnote tag // if FALSE, take content inside endnote tag
PRBool mAllContent; PRPackedBool mAllContent;
nsCOMPtr<nsIContent> mEndnote; nsCOMPtr<nsIContent> mEndnote;
}; };
@ -139,7 +142,7 @@ NS_NewXMLFragmentContentSink(nsIFragmentContentSink** aResult)
} }
nsXMLFragmentContentSink::nsXMLFragmentContentSink(PRBool aAllContent) nsXMLFragmentContentSink::nsXMLFragmentContentSink(PRBool aAllContent)
: mAllContent(aAllContent) : mParseError(PR_FALSE), mAllContent(aAllContent)
{ {
} }
@ -176,7 +179,7 @@ nsXMLFragmentContentSink::DidBuildModel()
{ {
PopContent(); // remove mRoot pushed above PopContent(); // remove mRoot pushed above
if (!mAllContent) { if (!mAllContent && !mParseError) {
NS_ASSERTION(mEndnote, "<endnote> missing in fragment string."); NS_ASSERTION(mEndnote, "<endnote> missing in fragment string.");
if (mEndnote) { if (mEndnote) {
NS_ASSERTION(mRoot->GetChildCount() == 1, "contents have too many children!"); NS_ASSERTION(mRoot->GetChildCount() == 1, "contents have too many children!");
@ -295,8 +298,40 @@ NS_IMETHODIMP
nsXMLFragmentContentSink::ReportError(const PRUnichar* aErrorText, nsXMLFragmentContentSink::ReportError(const PRUnichar* aErrorText,
const PRUnichar* aSourceText) const PRUnichar* aSourceText)
{ {
mParseError = PR_TRUE;
// The following error reporting is copied from nsXBLContentSink::ReportError()
nsCOMPtr<nsIConsoleService> consoleService =
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (consoleService) {
consoleService->LogStringMessage(aErrorText);
}
#ifdef DEBUG
// Report the error to stderr.
fprintf(stderr,
"\n%s\n%s\n\n",
NS_LossyConvertUCS2toASCII(aErrorText).get(),
NS_LossyConvertUCS2toASCII(aSourceText).get());
#endif
// The following code is similar to the cleanup in nsXMLContentSink::ReportError()
mState = eXMLContentSinkState_InProlog;
mNameSpaceStack.Clear();
// Clear the current content
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mRoot)); nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mRoot));
return ReportErrorFrom( aErrorText, aSourceText, node ); if (node) {
for (;;) {
nsCOMPtr<nsIDOMNode> child, dummy;
node->GetLastChild(getter_AddRefs(child));
if (!child)
break;
node->RemoveChild(child, getter_AddRefs(dummy));
}
}
return NS_OK;
} }
nsresult nsresult
@ -329,13 +364,15 @@ nsXMLFragmentContentSink::StartLayout()
NS_IMETHODIMP NS_IMETHODIMP
nsXMLFragmentContentSink::GetFragment(nsIDOMDocumentFragment** aFragment) nsXMLFragmentContentSink::GetFragment(nsIDOMDocumentFragment** aFragment)
{ {
if (mRoot) {
return CallQueryInterface(mRoot, aFragment);
}
*aFragment = nsnull; *aFragment = nsnull;
if (mParseError) {
return NS_OK; //XXX PARSE_ERR from DOM3 Load and Save would be more appropriate
return NS_ERROR_DOM_SYNTAX_ERR;
} else if (mRoot) {
return CallQueryInterface(mRoot, aFragment);
} else {
return NS_OK;
}
} }
NS_IMETHODIMP NS_IMETHODIMP