From 0b4ad7127ede127dba41e114f78a1f25dc3e83fd Mon Sep 17 00:00:00 2001 From: "timeless%mac.com" Date: Wed, 15 Aug 2001 06:48:59 +0000 Subject: [PATCH] Bug 83301 improve error reporting for Mismatched Tag XML, eg data:text/xml, r=heikki sr=shaver thanks to tingley@sundell.net and bz git-svn-id: svn://10.0.0.236/trunk@101088 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/htmlparser/src/nsExpatTokenizer.cpp | 59 ++++++++++++++++++- .../htmlparser/src/nsExpatTokenizer.cpp | 59 ++++++++++++++++++- 2 files changed, 112 insertions(+), 6 deletions(-) diff --git a/mozilla/htmlparser/src/nsExpatTokenizer.cpp b/mozilla/htmlparser/src/nsExpatTokenizer.cpp index 897bdee6262..66154226fe6 100644 --- a/mozilla/htmlparser/src/nsExpatTokenizer.cpp +++ b/mozilla/htmlparser/src/nsExpatTokenizer.cpp @@ -364,10 +364,11 @@ nsExpatTokenizer::AddErrorMessageTokens(nsParserError* aError) * in the content sink: * * - * XML Error: "contents of aError->description" - * Line Number: "contents of aError->lineNumber" + * XML Error: [aError->description] + * Location: [aError->sourceURL] + * Line Number: [aError->lineNumber], Column [aError->colNumber] * - * "Contents of aError->sourceLine" + * [aError->sourceLine] * "^ pointing at the error location" * * @@ -387,6 +388,58 @@ nsExpatTokenizer::PushXMLErrorTokens(const char *aBuffer, PRUint32 aLength, PRBo // Adjust the column number so that it is one based rather than zero based. error->colNumber = XML_GetCurrentColumnNumber(mExpatParser) + 1; error->description.AssignWithConversion(XML_ErrorString(error->code)); + if (error->code==XML_ERROR_TAG_MISMATCH){ + /* + * Certain things can be assumed about the token stream because of + * the way expat behaves. eg: + * + * - data:text/xml, is NOT WELL-FORMED + * - data:text/xml, is a TAG_MISMATCH. + * + * We can assume that there is at least one extra open tag (the one we + * want), so balance is initially set to one. + * + * Then loop through the tokens: + * - Each time we see eToken_end () increment balance, because + * that means there is another pair of tags we don't care about. + * - Each time we see eToken_start () decrement balance because it + * matches a close tag (perhaps the MISMATCHed tag in which case + * balance should hit 0). + * - If balance ever hits zero, exit the loop. Because of the way + * balance is adjusted, if balance is zero expected *must* be a start + * tag. + * + * We must check expected in the condition in case expat or nsDeque go + * crazy and give us 0 (null) before balance reaches 0. + */ + nsDequeIterator current = mState->tokenDeque->End(); + CToken *expected = NS_STATIC_CAST(CToken*,--current); + PRUint32 balance = 1; + + while (expected) { + switch (expected->GetTokenType()) { + case eToken_start: + --balance; + break; + case eToken_end: + ++balance; + break; + default: + break; // we don't care about newlines or other tokens + } + + if (!balance) { + // if balance is zero, this must be a start tag + CStartToken *startToken=NS_STATIC_CAST(CStartToken*,expected); + error->description.Append(NS_LITERAL_STRING(". Expected: description.Append(startToken->GetStringValue()); + error->description.Append(NS_LITERAL_STRING(">")); + break; + } + + expected = NS_STATIC_CAST(CToken*,--current); + } + } error->sourceURL.Assign((PRUnichar*)XML_GetBase(mExpatParser)); if (!aIsFinal) { PRInt32 byteIndexRelativeToFile = 0; diff --git a/mozilla/parser/htmlparser/src/nsExpatTokenizer.cpp b/mozilla/parser/htmlparser/src/nsExpatTokenizer.cpp index 897bdee6262..66154226fe6 100644 --- a/mozilla/parser/htmlparser/src/nsExpatTokenizer.cpp +++ b/mozilla/parser/htmlparser/src/nsExpatTokenizer.cpp @@ -364,10 +364,11 @@ nsExpatTokenizer::AddErrorMessageTokens(nsParserError* aError) * in the content sink: * * - * XML Error: "contents of aError->description" - * Line Number: "contents of aError->lineNumber" + * XML Error: [aError->description] + * Location: [aError->sourceURL] + * Line Number: [aError->lineNumber], Column [aError->colNumber] * - * "Contents of aError->sourceLine" + * [aError->sourceLine] * "^ pointing at the error location" * * @@ -387,6 +388,58 @@ nsExpatTokenizer::PushXMLErrorTokens(const char *aBuffer, PRUint32 aLength, PRBo // Adjust the column number so that it is one based rather than zero based. error->colNumber = XML_GetCurrentColumnNumber(mExpatParser) + 1; error->description.AssignWithConversion(XML_ErrorString(error->code)); + if (error->code==XML_ERROR_TAG_MISMATCH){ + /* + * Certain things can be assumed about the token stream because of + * the way expat behaves. eg: + * + * - data:text/xml, is NOT WELL-FORMED + * - data:text/xml, is a TAG_MISMATCH. + * + * We can assume that there is at least one extra open tag (the one we + * want), so balance is initially set to one. + * + * Then loop through the tokens: + * - Each time we see eToken_end () increment balance, because + * that means there is another pair of tags we don't care about. + * - Each time we see eToken_start () decrement balance because it + * matches a close tag (perhaps the MISMATCHed tag in which case + * balance should hit 0). + * - If balance ever hits zero, exit the loop. Because of the way + * balance is adjusted, if balance is zero expected *must* be a start + * tag. + * + * We must check expected in the condition in case expat or nsDeque go + * crazy and give us 0 (null) before balance reaches 0. + */ + nsDequeIterator current = mState->tokenDeque->End(); + CToken *expected = NS_STATIC_CAST(CToken*,--current); + PRUint32 balance = 1; + + while (expected) { + switch (expected->GetTokenType()) { + case eToken_start: + --balance; + break; + case eToken_end: + ++balance; + break; + default: + break; // we don't care about newlines or other tokens + } + + if (!balance) { + // if balance is zero, this must be a start tag + CStartToken *startToken=NS_STATIC_CAST(CStartToken*,expected); + error->description.Append(NS_LITERAL_STRING(". Expected: description.Append(startToken->GetStringValue()); + error->description.Append(NS_LITERAL_STRING(">")); + break; + } + + expected = NS_STATIC_CAST(CToken*,--current); + } + } error->sourceURL.Assign((PRUnichar*)XML_GetBase(mExpatParser)); if (!aIsFinal) { PRInt32 byteIndexRelativeToFile = 0;