[SCM] WebKit Debian packaging branch, webkit-1.2, updated. upstream/1.1.90-6072-g9a69373

oliver at apple.com oliver at apple.com
Thu Apr 8 00:31:34 UTC 2010


The following commit has been merged in the webkit-1.2 branch:
commit 899eae85ae40d0158c7ac2672faf8ca8fa51912e
Author: oliver at apple.com <oliver at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Dec 10 22:06:31 2009 +0000

    Crash in XMLTokenizer::popCurrentNode if window.close() is called during parsing
    https://bugs.webkit.org/show_bug.cgi?id=31576
    
    Reviewed by Alexey Proskuryakov.
    
    Add a RefCounted wrapper object around xmlParserCtxtPtr so we can
    maintain it's lifetime more effectively.
    
    Test: fast/parser/xhtml-close-while-parsing.xhtml
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@51962 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 14f7f6c..e40a1d5 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,16 @@
+2009-12-10  Oliver Hunt  <oliver at apple.com>
+
+        Reviewed by Alexey Proskuryakov.
+
+        Crash in XMLTokenizer::popCurrentNode if window.close() is called during parsing
+        https://bugs.webkit.org/show_bug.cgi?id=31576
+
+        Add test of window.close() during XML parsing.
+
+        * fast/parser/resources/xhtml-close-while-parsing-target.xhtml: Added.
+        * fast/parser/xhtml-close-while-parsing-expected.txt: Added.
+        * fast/parser/xhtml-close-while-parsing.xhtml: Added.
+
 2009-12-10  Dimitri Glazkov  <dglazkov at chromium.org>
 
         Reviewed by Adam Barth.
diff --git a/LayoutTests/fast/parser/resources/xhtml-close-while-parsing-target.xhtml b/LayoutTests/fast/parser/resources/xhtml-close-while-parsing-target.xhtml
new file mode 100644
index 0000000..39090ff
--- /dev/null
+++ b/LayoutTests/fast/parser/resources/xhtml-close-while-parsing-target.xhtml
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<body>
+    <script>
+    window.close();
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+    </script>
+</body>
+</html>
diff --git a/LayoutTests/fast/parser/xhtml-close-while-parsing-expected.txt b/LayoutTests/fast/parser/xhtml-close-while-parsing-expected.txt
new file mode 100644
index 0000000..816a0c9
--- /dev/null
+++ b/LayoutTests/fast/parser/xhtml-close-while-parsing-expected.txt
@@ -0,0 +1 @@
+This tests that the XML parser doesn't fail if window.close() is called from a script tag while parsing. If you see this text the test has passed.
diff --git a/LayoutTests/fast/parser/xhtml-close-while-parsing.xhtml b/LayoutTests/fast/parser/xhtml-close-while-parsing.xhtml
new file mode 100644
index 0000000..6528fcf
--- /dev/null
+++ b/LayoutTests/fast/parser/xhtml-close-while-parsing.xhtml
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<body>
+    This tests that the XML parser doesn't fail if window.close() is called from a script tag while parsing.
+    <script>
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.setCanOpenWindows();
+        layoutTestController.waitUntilDone();
+    }
+        
+    window.open("resources/xhtml-close-while-parsing-target.xhtml");
+    </script>
+    If you see this text the test has passed.
+</body>
+</html>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 659015d..810c510 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,35 @@
+2009-12-10  Oliver Hunt  <oliver at apple.com>
+
+        Reviewed by Alexey Proskuryakov.
+
+        Crash in XMLTokenizer::popCurrentNode if window.close() is called during parsing
+        https://bugs.webkit.org/show_bug.cgi?id=31576
+
+        Add a RefCounted wrapper object around xmlParserCtxtPtr so we can
+        maintain it's lifetime more effectively.
+
+        Test: fast/parser/xhtml-close-while-parsing.xhtml
+
+        * dom/XMLTokenizer.cpp:
+        (WebCore::XMLTokenizer::popCurrentNode):
+        * dom/XMLTokenizer.h:
+        (WebCore::XMLParserContext::context):
+        (WebCore::XMLParserContext::XMLParserContext):
+        (WebCore::XMLTokenizer::context):
+        * dom/XMLTokenizerLibxml2.cpp:
+        (WebCore::XMLParserContext::createStringParser):
+        (WebCore::XMLParserContext::createMemoryParser):
+        (WebCore::XMLParserContext::~XMLParserContext):
+        (WebCore::XMLTokenizer::~XMLTokenizer):
+        (WebCore::XMLTokenizer::doWrite):
+        (WebCore::XMLTokenizer::initializeParserContext):
+        (WebCore::XMLTokenizer::doEnd):
+        (WebCore::XMLTokenizer::lineNumber):
+        (WebCore::XMLTokenizer::columnNumber):
+        (WebCore::XMLTokenizer::stopParsing):
+        (WebCore::parseXMLDocumentFragment):
+        (WebCore::parseAttributes):
+
 2009-12-10  Pavel Feldman  <pfeldman at chromium.org>
 
         Reviewed by Timothy Hatcher.
diff --git a/WebCore/dom/XMLTokenizer.cpp b/WebCore/dom/XMLTokenizer.cpp
index 30d39e0..56f8ff4 100644
--- a/WebCore/dom/XMLTokenizer.cpp
+++ b/WebCore/dom/XMLTokenizer.cpp
@@ -91,7 +91,8 @@ void XMLTokenizer::pushCurrentNode(Node* n)
 
 void XMLTokenizer::popCurrentNode()
 {
-    ASSERT(m_currentNode);
+    if (!m_currentNode)
+        return;
     ASSERT(m_currentNodeStack.size());
 
     if (m_currentNode != m_doc)
diff --git a/WebCore/dom/XMLTokenizer.h b/WebCore/dom/XMLTokenizer.h
index e1ee09f..2d6fefc 100644
--- a/WebCore/dom/XMLTokenizer.h
+++ b/WebCore/dom/XMLTokenizer.h
@@ -52,6 +52,23 @@ namespace WebCore {
     class PendingCallbacks;
     class ScriptElement;
 
+#if !USE(QXMLSTREAM)
+    class XMLParserContext : public RefCounted<XMLParserContext> {
+    public:
+        static PassRefPtr<XMLParserContext> createMemoryParser(xmlSAXHandlerPtr, void*, const char*);
+        static PassRefPtr<XMLParserContext> createStringParser(xmlSAXHandlerPtr, void*);
+        ~XMLParserContext();
+        xmlParserCtxtPtr context() const { return m_context; }
+
+    private:
+        XMLParserContext(xmlParserCtxtPtr context)
+            : m_context(context)
+        {
+        }
+        xmlParserCtxtPtr m_context;
+    };
+#endif
+
     class XMLTokenizer : public Tokenizer, public CachedResourceClient {
     public:
         XMLTokenizer(Document*, FrameView* = 0);
@@ -146,7 +163,8 @@ public:
         QXmlStreamReader m_stream;
         bool m_wroteText;
 #else
-        xmlParserCtxtPtr m_context;
+        xmlParserCtxtPtr context() const { return m_context ? m_context->context() : 0; };
+        RefPtr<XMLParserContext> m_context;
         OwnPtr<PendingCallbacks> m_pendingCallbacks;
         Vector<xmlChar> m_bufferedText;
 #endif
diff --git a/WebCore/dom/XMLTokenizerLibxml2.cpp b/WebCore/dom/XMLTokenizerLibxml2.cpp
index 9aa0961..42c8b9b 100644
--- a/WebCore/dom/XMLTokenizerLibxml2.cpp
+++ b/WebCore/dom/XMLTokenizerLibxml2.cpp
@@ -465,7 +465,7 @@ static void errorFunc(void*, const char*, ...)
 
 static bool didInit = false;
 
-static xmlParserCtxtPtr createStringParser(xmlSAXHandlerPtr handlers, void* userData)
+PassRefPtr<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerPtr handlers, void* userData)
 {
     if (!didInit) {
         xmlInitParser();
@@ -482,12 +482,12 @@ static xmlParserCtxtPtr createStringParser(xmlSAXHandlerPtr handlers, void* user
     const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
     xmlSwitchEncoding(parser, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
 
-    return parser;
+    return adoptRef(new XMLParserContext(parser));
 }
 
 
 // Chunk should be encoded in UTF-8
-static xmlParserCtxtPtr createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const char* chunk)
+PassRefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const char* chunk)
 {
     if (!didInit) {
         xmlInitParser();
@@ -518,8 +518,8 @@ static xmlParserCtxtPtr createMemoryParser(xmlSAXHandlerPtr handlers, void* user
     parser->str_xmlns = xmlDictLookup(parser->dict, BAD_CAST "xmlns", 5);
     parser->str_xml_ns = xmlDictLookup(parser->dict, XML_XML_NAMESPACE, 36);
     parser->_private = userData;
-
-    return parser;
+    
+    return adoptRef(new XMLParserContext(parser));
 }
 
 // --------------------------------
@@ -609,6 +609,13 @@ XMLTokenizer::XMLTokenizer(DocumentFragment* fragment, Element* parentElement)
         m_defaultNamespaceURI = parentElement->namespaceURI();
 }
 
+XMLParserContext::~XMLParserContext()
+{
+    if (m_context->myDoc)
+        xmlFreeDoc(m_context->myDoc);
+    xmlFreeParserCtxt(m_context);
+}
+
 XMLTokenizer::~XMLTokenizer()
 {
     clearCurrentNodeStack();
@@ -616,15 +623,16 @@ XMLTokenizer::~XMLTokenizer()
         m_doc->deref();
     if (m_pendingScript)
         m_pendingScript->removeClient(this);
-    if (m_context)
-        xmlFreeParserCtxt(m_context);
 }
 
 void XMLTokenizer::doWrite(const String& parseString)
 {
     if (!m_context)
         initializeParserContext();
-    
+
+    // Protect the libxml context from deletion during a callback
+    RefPtr<XMLParserContext> context = m_context;
+
     // libXML throws an error if you try to switch the encoding for an empty string.
     if (parseString.length()) {
         // Hack around libxml2's lack of encoding overide support by manually
@@ -633,15 +641,15 @@ void XMLTokenizer::doWrite(const String& parseString)
         // and switch encodings, causing the parse to fail.
         const UChar BOM = 0xFEFF;
         const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
-        xmlSwitchEncoding(m_context, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
+        xmlSwitchEncoding(context->context(), BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
 
         XMLTokenizerScope scope(m_doc->docLoader());
-        xmlParseChunk(m_context, reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0);
+        xmlParseChunk(context->context(), reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0);
     }
     
     if (m_doc->decoder() && m_doc->decoder()->sawError()) {
         // If the decoder saw an error, report it as fatal (stops parsing)
-        handleError(fatal, "Encoding error", lineNumber(), columnNumber());
+        handleError(fatal, "Encoding error", context->context()->input->line, context->context()->input->col);
     }
 
     return;
@@ -1277,9 +1285,9 @@ void XMLTokenizer::initializeParserContext(const char* chunk)
 
     XMLTokenizerScope scope(m_doc->docLoader());
     if (m_parsingFragment)
-        m_context = createMemoryParser(&sax, this, chunk);
+        m_context = XMLParserContext::createMemoryParser(&sax, this, chunk);
     else
-        m_context = createStringParser(&sax, this);
+        m_context = XMLParserContext::createStringParser(&sax, this);
 }
 
 void XMLTokenizer::doEnd()
@@ -1300,12 +1308,9 @@ void XMLTokenizer::doEnd()
         // Tell libxml we're done.
         {
             XMLTokenizerScope scope(m_doc->docLoader());
-            xmlParseChunk(m_context, 0, 0, 1);
+            xmlParseChunk(context(), 0, 0, 1);
         }
 
-        if (m_context->myDoc)
-            xmlFreeDoc(m_context->myDoc);
-        xmlFreeParserCtxt(m_context);
         m_context = 0;
     }
 }
@@ -1334,18 +1339,19 @@ void* xmlDocPtrForString(DocLoader* docLoader, const String& source, const Strin
 
 int XMLTokenizer::lineNumber() const
 {
-    return m_context ? m_context->input->line : 1;
+    return context() ? context()->input->line : 1;
 }
 
 int XMLTokenizer::columnNumber() const
 {
-    return m_context ? m_context->input->col : 1;
+    return context() ? context()->input->col : 1;
 }
 
 void XMLTokenizer::stopParsing()
 {
     Tokenizer::stopParsing();
-    xmlStopParser(m_context);
+    if (context())
+        xmlStopParser(context());
 }
 
 void XMLTokenizer::resumeParsing()
@@ -1384,17 +1390,17 @@ bool parseXMLDocumentFragment(const String& chunk, DocumentFragment* fragment, E
     CString chunkAsUtf8 = chunk.utf8();
     tokenizer.initializeParserContext(chunkAsUtf8.data());
 
-    xmlParseContent(tokenizer.m_context);
+    xmlParseContent(tokenizer.context());
 
     tokenizer.endDocument();
 
     // Check if all the chunk has been processed.
-    long bytesProcessed = xmlByteConsumed(tokenizer.m_context);
+    long bytesProcessed = xmlByteConsumed(tokenizer.context());
     if (bytesProcessed == -1 || ((unsigned long)bytesProcessed) != chunkAsUtf8.length())
         return false;
 
     // No error if the chunk is well formed or it is not but we have no error.
-    return tokenizer.m_context->wellFormed || xmlCtxtGetLastError(tokenizer.m_context) == 0;
+    return tokenizer.context()->wellFormed || xmlCtxtGetLastError(tokenizer.context()) == 0;
 }
 
 // --------------------------------
@@ -1437,12 +1443,9 @@ HashMap<String, String> parseAttributes(const String& string, bool& attrsOK)
     memset(&sax, 0, sizeof(sax));
     sax.startElementNs = attributesStartElementNsHandler;
     sax.initialized = XML_SAX2_MAGIC;
-    xmlParserCtxtPtr parser = createStringParser(&sax, &state);
+    RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax, &state);
     String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />";
-    xmlParseChunk(parser, reinterpret_cast<const char*>(parseString.characters()), parseString.length() * sizeof(UChar), 1);
-    if (parser->myDoc)
-        xmlFreeDoc(parser->myDoc);
-    xmlFreeParserCtxt(parser);
+    xmlParseChunk(parser->context(), reinterpret_cast<const char*>(parseString.characters()), parseString.length() * sizeof(UChar), 1);
     attrsOK = state.gotAttributes;
     return state.attributes;
 }

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list