Title: [123788] trunk
Revision
123788
Author
rn...@webkit.org
Date
2012-07-26 13:23:09 -0700 (Thu, 26 Jul 2012)

Log Message

Href attribute with _javascript_ protocol is stripped when content is pasted into a XML doucment
https://bugs.webkit.org/show_bug.cgi?id=92310

Reviewed by Adam Barth.

Source/WebCore: 

The bug was caused by setAttributeNS's stripping attributes for which isAttributeToRemove
return true instead of setting an empty string. Changing this in setAttributeNS is problematic
because it will trigger a logic, in HTMLAnchorElement for example, to resolve the URL.

Fixed the bug by making XML parsers call parserSetAttributes instead of setAttributeNS.
After this patch, handleNamespaceAttributes and handleElementAttributes simply fills up a Vector
with which startElementNs (or parseStartElement in Qt) calls parserSetAttributes.

* dom/Element.cpp:
(WebCore::Element::parserSetAttributes): Sets emptyAtom instead of nullAtom as nullAtom can be
turned into "null".
(WebCore::Element::parseAttributeName): Extracted from setAttributeNS.
(WebCore::Element::setAttributeNS): No longer takes FragmentScriptingPermission.
* dom/Element.h:
(Element):
* editing/markup.cpp:
(WebCore::completeURLs): Don't resolve URLs when it's empty since empty attribute has a canonical
meaning in some cases. e.g. <frame src=""
* xml/parser/XMLDocumentParserLibxml2.cpp:
(WebCore::handleNamespaceAttributes): Renamed from handleElementNamespaces. Call
parserSetAttributes even when exiting early to be maintain the same behavior.
(WebCore::handleElementAttributes):
(WebCore::XMLDocumentParser::startElementNs):
* xml/parser/XMLDocumentParserQt.cpp:
(WebCore::handleNamespaceAttributes): Use XMLNSNames::xmlnsNamespaceURI. Call parserSetAttributes
even when exiting early to be maintain the same behavior.
(WebCore::handleElementAttributes):
(WebCore::XMLDocumentParser::parseStartElement):

LayoutTests: 

Rebaseline a test that catches this bug.

* editing/pasteboard/paste-noscript-xhtml-expected.txt:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (123787 => 123788)


--- trunk/LayoutTests/ChangeLog	2012-07-26 20:19:39 UTC (rev 123787)
+++ trunk/LayoutTests/ChangeLog	2012-07-26 20:23:09 UTC (rev 123788)
@@ -1,3 +1,14 @@
+2012-07-25  Ryosuke Niwa  <rn...@webkit.org>
+
+        Href attribute with _javascript_ protocol is stripped when content is pasted into a XML doucment
+        https://bugs.webkit.org/show_bug.cgi?id=92310
+
+        Reviewed by Adam Barth.
+
+        Rebaseline a test that catches this bug.
+
+        * editing/pasteboard/paste-noscript-xhtml-expected.txt:
+
 2012-07-26  Dan Bernstein  <m...@apple.com>
 
         <svg> element with no intrinsic size and max-width gets sized incorrectly

Modified: trunk/LayoutTests/editing/pasteboard/paste-noscript-xhtml-expected.txt (123787 => 123788)


--- trunk/LayoutTests/editing/pasteboard/paste-noscript-xhtml-expected.txt	2012-07-26 20:19:39 UTC (rev 123787)
+++ trunk/LayoutTests/editing/pasteboard/paste-noscript-xhtml-expected.txt	2012-07-26 20:23:09 UTC (rev 123788)
@@ -63,12 +63,15 @@
 |   id="anchor1"
 |   "CNN"
 | <a>
+|   href=""
 |   id="anchor2"
 |   "Hello"
 | <iframe>
 |   id="iframe1"
+|   src=""
 |   style="width: 200px; height: 100px; background-color: rgb(204, 238, 238); "
 | <form>
+|   action=""
 |   id="form1"
 |   style="width: 200px; height: 150px; background-color: rgb(204, 238, 238); "
 |   "This is a form<#selection-caret>"

Modified: trunk/Source/WebCore/ChangeLog (123787 => 123788)


--- trunk/Source/WebCore/ChangeLog	2012-07-26 20:19:39 UTC (rev 123787)
+++ trunk/Source/WebCore/ChangeLog	2012-07-26 20:23:09 UTC (rev 123788)
@@ -1,3 +1,39 @@
+2012-07-26  Ryosuke Niwa  <rn...@webkit.org>
+
+        Href attribute with _javascript_ protocol is stripped when content is pasted into a XML doucment
+        https://bugs.webkit.org/show_bug.cgi?id=92310
+
+        Reviewed by Adam Barth.
+
+        The bug was caused by setAttributeNS's stripping attributes for which isAttributeToRemove
+        return true instead of setting an empty string. Changing this in setAttributeNS is problematic
+        because it will trigger a logic, in HTMLAnchorElement for example, to resolve the URL.
+
+        Fixed the bug by making XML parsers call parserSetAttributes instead of setAttributeNS.
+        After this patch, handleNamespaceAttributes and handleElementAttributes simply fills up a Vector
+        with which startElementNs (or parseStartElement in Qt) calls parserSetAttributes.
+
+        * dom/Element.cpp:
+        (WebCore::Element::parserSetAttributes): Sets emptyAtom instead of nullAtom as nullAtom can be
+        turned into "null".
+        (WebCore::Element::parseAttributeName): Extracted from setAttributeNS.
+        (WebCore::Element::setAttributeNS): No longer takes FragmentScriptingPermission.
+        * dom/Element.h:
+        (Element):
+        * editing/markup.cpp:
+        (WebCore::completeURLs): Don't resolve URLs when it's empty since empty attribute has a canonical
+        meaning in some cases. e.g. <frame src=""
+        * xml/parser/XMLDocumentParserLibxml2.cpp:
+        (WebCore::handleNamespaceAttributes): Renamed from handleElementNamespaces. Call
+        parserSetAttributes even when exiting early to be maintain the same behavior.
+        (WebCore::handleElementAttributes):
+        (WebCore::XMLDocumentParser::startElementNs):
+        * xml/parser/XMLDocumentParserQt.cpp:
+        (WebCore::handleNamespaceAttributes): Use XMLNSNames::xmlnsNamespaceURI. Call parserSetAttributes
+        even when exiting early to be maintain the same behavior.
+        (WebCore::handleElementAttributes):
+        (WebCore::XMLDocumentParser::parseStartElement):
+
 2012-07-26  Dan Bernstein  <m...@apple.com>
 
         <svg> element with no intrinsic size and max-width gets sized incorrectly

Modified: trunk/Source/WebCore/dom/Element.cpp (123787 => 123788)


--- trunk/Source/WebCore/dom/Element.cpp	2012-07-26 20:19:39 UTC (rev 123787)
+++ trunk/Source/WebCore/dom/Element.cpp	2012-07-26 20:23:09 UTC (rev 123788)
@@ -784,7 +784,7 @@
             }
 
             if (isAttributeToRemove(attribute.name(), attribute.value()))
-                attribute.setValue(nullAtom);
+                attribute.setValue(emptyAtom);
             i++;
         }
     }
@@ -1462,23 +1462,30 @@
     return detachAttribute(index);
 }
 
-void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
+bool Element::parseAttributeName(QualifiedName& out, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionCode& ec)
 {
     String prefix, localName;
     if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
-        return;
+        return false;
+    ASSERT(!ec);
 
     QualifiedName qName(prefix, localName, namespaceURI);
 
     if (!Document::hasValidNamespaceForAttributes(qName)) {
         ec = NAMESPACE_ERR;
-        return;
+        return false;
     }
 
-    if (scriptingPermission == DisallowScriptingContent && (isEventHandlerAttribute(qName) || isAttributeToRemove(qName, value)))
+    out = qName;
+    return true;
+}
+
+void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec)
+{
+    QualifiedName parsedName = anyName;
+    if (!parseAttributeName(parsedName, namespaceURI, qualifiedName, ec))
         return;
-
-    setAttribute(qName, value);
+    setAttribute(parsedName, value);
 }
 
 void Element::removeAttribute(size_t index)

Modified: trunk/Source/WebCore/dom/Element.h (123787 => 123788)


--- trunk/Source/WebCore/dom/Element.h	2012-07-26 20:19:39 UTC (rev 123787)
+++ trunk/Source/WebCore/dom/Element.h	2012-07-26 20:23:09 UTC (rev 123788)
@@ -146,7 +146,8 @@
     const AtomicString& getAttributeNS(const String& namespaceURI, const String& localName) const;
 
     void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
-    void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&, FragmentScriptingPermission = AllowScriptingContent);
+    static bool parseAttributeName(QualifiedName&, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionCode&);
+    void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&);
 
     bool isIdAttributeName(const QualifiedName&) const;
     const AtomicString& getIdAttribute() const;

Modified: trunk/Source/WebCore/editing/markup.cpp (123787 => 123788)


--- trunk/Source/WebCore/editing/markup.cpp	2012-07-26 20:19:39 UTC (rev 123787)
+++ trunk/Source/WebCore/editing/markup.cpp	2012-07-26 20:23:09 UTC (rev 123788)
@@ -111,7 +111,7 @@
             unsigned length = e->attributeCount();
             for (unsigned i = 0; i < length; i++) {
                 const Attribute* attribute = e->attributeItem(i);
-                if (e->isURLAttribute(*attribute))
+                if (e->isURLAttribute(*attribute) && !attribute->value().isEmpty())
                     changes.append(AttributeChange(e, attribute->name(), KURL(parsedBaseURL, attribute->value()).string()));
             }
         }

Modified: trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp (123787 => 123788)


--- trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp	2012-07-26 20:19:39 UTC (rev 123787)
+++ trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp	2012-07-26 20:23:09 UTC (rev 123788)
@@ -696,7 +696,7 @@
 };
 typedef struct _xmlSAX2Namespace xmlSAX2Namespace;
 
-static inline void handleElementNamespaces(Element* newElement, const xmlChar** libxmlNamespaces, int nb_namespaces, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
+static inline void handleNamespaceAttributes(Vector<Attribute, 8>& prefixedAttributes, const xmlChar** libxmlNamespaces, int nb_namespaces, ExceptionCode& ec)
 {
     xmlSAX2Namespace* namespaces = reinterpret_cast<xmlSAX2Namespace*>(libxmlNamespaces);
     for (int i = 0; i < nb_namespaces; i++) {
@@ -704,9 +704,12 @@
         AtomicString namespaceURI = toAtomicString(namespaces[i].uri);
         if (namespaces[i].prefix)
             namespaceQName = "xmlns:" + toString(namespaces[i].prefix);
-        newElement->setAttributeNS(XMLNSNames::xmlnsNamespaceURI, namespaceQName, namespaceURI, ec, scriptingPermission);
-        if (ec) // exception setting attributes
+
+        QualifiedName parsedName = anyName;
+        if (!Element::parseAttributeName(parsedName, XMLNSNames::xmlnsNamespaceURI, namespaceQName, ec))
             return;
+        
+        prefixedAttributes.append(Attribute(parsedName, namespaceURI));
     }
 }
 
@@ -719,7 +722,7 @@
 };
 typedef struct _xmlSAX2Attributes xmlSAX2Attributes;
 
-static inline void handleElementAttributes(Element* newElement, const xmlChar** libxmlAttributes, int nb_attributes, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
+static inline void handleElementAttributes(Vector<Attribute, 8>& prefixedAttributes, const xmlChar** libxmlAttributes, int nb_attributes, ExceptionCode& ec)
 {
     xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlAttributes);
     for (int i = 0; i < nb_attributes; i++) {
@@ -729,9 +732,11 @@
         AtomicString attrURI = attrPrefix.isEmpty() ? AtomicString() : toAtomicString(attributes[i].uri);
         AtomicString attrQName = attrPrefix.isEmpty() ? toAtomicString(attributes[i].localname) : attrPrefix + ":" + toString(attributes[i].localname);
 
-        newElement->setAttributeNS(attrURI, attrQName, attrValue, ec, scriptingPermission);
-        if (ec) // exception setting attributes
+        QualifiedName parsedName = anyName;
+        if (!Element::parseAttributeName(parsedName, attrURI, attrQName, ec))
             return;
+
+        prefixedAttributes.append(Attribute(parsedName, attrValue));
     }
 }
 
@@ -788,14 +793,17 @@
         return;
     }
 
+    Vector<Attribute, 8> prefixedAttributes;
     ExceptionCode ec = 0;
-    handleElementNamespaces(newElement.get(), libxmlNamespaces, nb_namespaces, ec, m_scriptingPermission);
+    handleNamespaceAttributes(prefixedAttributes, libxmlNamespaces, nb_namespaces, ec);
     if (ec) {
+        newElement->parserSetAttributes(prefixedAttributes, m_scriptingPermission);
         stopParsing();
         return;
     }
 
-    handleElementAttributes(newElement.get(), libxmlAttributes, nb_attributes, ec, m_scriptingPermission);
+    handleElementAttributes(prefixedAttributes, libxmlAttributes, nb_attributes, ec);
+    newElement->parserSetAttributes(prefixedAttributes, m_scriptingPermission);
     if (ec) {
         stopParsing();
         return;

Modified: trunk/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp (123787 => 123788)


--- trunk/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp	2012-07-26 20:19:39 UTC (rev 123787)
+++ trunk/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp	2012-07-26 20:23:09 UTC (rev 123788)
@@ -52,6 +52,7 @@
 #include "ScriptValue.h"
 #include "TextResourceDecoder.h"
 #include "TransformSource.h"
+#include "XMLNSNames.h"
 #include <QDebug>
 #include <wtf/StringExtras.h>
 #include <wtf/Threading.h>
@@ -315,22 +316,23 @@
         return qName.left(offset);
 }
 
-static inline void handleElementNamespaces(Element* newElement, const QXmlStreamNamespaceDeclarations &ns,
-                                           ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
+static inline void handleNamespaceAttributes(Vector<Attribute, 8>& prefixedAttributes, const QXmlStreamNamespaceDeclarations &ns, ExceptionCode& ec)
 {
     for (int i = 0; i < ns.count(); ++i) {
         const QXmlStreamNamespaceDeclaration &decl = ns[i];
         String namespaceURI = decl.namespaceUri();
         String namespaceQName = decl.prefix().isEmpty() ? String("xmlns") : String("xmlns:");
         namespaceQName.append(decl.prefix());
-        newElement->setAttributeNS("http://www.w3.org/2000/xmlns/", namespaceQName, namespaceURI, ec, scriptingPermission);
-        if (ec) // exception setting attributes
+
+        QualifiedName parsedName = anyName;
+        if (!Element::parseAttributeName(parsedName, XMLNSNames::xmlnsNamespaceURI, namespaceQName, ec))
             return;
+
+        prefixedAttributes.append(Attribute(parsedName, namespaceURI));
     }
 }
 
-static inline void handleElementAttributes(Element* newElement, const QXmlStreamAttributes &attrs, ExceptionCode& ec,
-                                           FragmentScriptingPermission scriptingPermission)
+static inline void handleElementAttributes(Vector<Attribute, 8>& prefixedAttributes, const QXmlStreamAttributes &attrs, ExceptionCode& ec)
 {
     for (int i = 0; i < attrs.count(); ++i) {
         const QXmlStreamAttribute &attr = attrs[i];
@@ -338,9 +340,12 @@
         String attrValue     = attr.value();
         String attrURI       = attr.namespaceUri().isEmpty() ? String() : String(attr.namespaceUri());
         String attrQName     = attr.qualifiedName();
-        newElement->setAttributeNS(attrURI, attrQName, attrValue, ec, scriptingPermission);
-        if (ec) // exception setting attributes
+
+        QualifiedName parsedName = anyName;
+        if (!Element::parseAttributeName(parsedName, attrURI, attrQName, ec))
             return;
+
+        prefixedAttributes.append(Attribute(parsedName, attrURI));
     }
 }
 
@@ -455,14 +460,17 @@
     bool isFirstElement = !m_sawFirstElement;
     m_sawFirstElement = true;
 
+    Vector<Attribute, 8> prefixedAttributes;
     ExceptionCode ec = 0;
-    handleElementNamespaces(newElement.get(), m_stream.namespaceDeclarations(), ec, m_scriptingPermission);
+    handleNamespaceAttributes(prefixedAttributes, m_stream.namespaceDeclarations(), ec);
     if (ec) {
+        newElement->parserSetAttributes(prefixedAttributes, m_scriptingPermission);
         stopParsing();
         return;
     }
 
-    handleElementAttributes(newElement.get(), m_stream.attributes(), ec, m_scriptingPermission);
+    handleElementAttributes(prefixedAttributes, m_stream.attributes(), ec);
+    newElement->parserSetAttributes(prefixedAttributes, m_scriptingPermission);
     if (ec) {
         stopParsing();
         return;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to