Reserved namespaces in xsl:element and xsl:attribute
authorNick Wellnhofer <wellnhofer@aevum.de>
Wed, 15 Aug 2012 21:50:22 +0000 (23:50 +0200)
committerDaniel Veillard <veillard@redhat.com>
Thu, 6 Sep 2012 12:41:46 +0000 (20:41 +0800)
For https://bugzilla.gnome.org/show_bug.cgi?id=587360

Correct handling of 'xml' and 'xmlns' namespaces in xsl:element and
xsl:attribute.

libxslt/attributes.c
libxslt/transform.c
tests/docs/bug-177.xml [new file with mode: 0644]
tests/general/Makefile.am
tests/general/bug-177.out [new file with mode: 0644]
tests/general/bug-177.xsl [new file with mode: 0644]

index 11d558b..a584d22 100644 (file)
@@ -822,7 +822,19 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt,
            if ((tmpNsName != NULL) && (tmpNsName[0] != 0))
                nsName = xmlDictLookup(ctxt->dict, BAD_CAST tmpNsName, -1);
            xmlFree(tmpNsName);         
-       };          
+       }
+
+        if (xmlStrEqual(nsName, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
+            xsltTransformError(ctxt, NULL, inst,
+                "xsl:attribute: Namespace http://www.w3.org/2000/xmlns/ "
+                "forbidden.\n");
+            goto error;
+        }
+        if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
+            prefix = BAD_CAST "xml";
+        } else if (xmlStrEqual(prefix, BAD_CAST "xml")) {
+            prefix = NULL;
+        }
     } else if (prefix != NULL) {
        /*
        * SPEC XSLT 1.0:
index bc6d851..4c6b2a5 100644 (file)
@@ -3978,14 +3978,6 @@ xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
        }
        name = xsltSplitQName(ctxt->dict, prop, &prefix);
        xmlFree(prop);
-       if ((prefix != NULL) &&
-           (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)))
-       {
-           /*
-           * TODO: Should we really disallow an "xml" prefix?
-           */
-           goto error;
-       }
     } else {
        /*
        * The "name" value was static.
@@ -4040,8 +4032,20 @@ xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
            if ((tmpNsName != NULL) && (tmpNsName[0] != 0))
                nsName = xmlDictLookup(ctxt->dict, BAD_CAST tmpNsName, -1);
            xmlFree(tmpNsName);
-       };
-    } else {
+       }
+
+        if (xmlStrEqual(nsName, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
+            xsltTransformError(ctxt, NULL, inst,
+                "xsl:attribute: Namespace http://www.w3.org/2000/xmlns/ "
+                "forbidden.\n");
+            goto error;
+        }
+        if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
+            prefix = BAD_CAST "xml";
+        } else if (xmlStrEqual(prefix, BAD_CAST "xml")) {
+            prefix = NULL;
+        }
+    } else if (prefix != NULL) {
        xmlNsPtr ns;
        /*
        * SPEC XSLT 1.0:
@@ -4056,13 +4060,11 @@ xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
            * TODO: Check this in the compilation layer in case it's a
            * static value.
            */
-           if (prefix != NULL) {
-               xsltTransformError(ctxt, NULL, inst,
-                   "xsl:element: The QName '%s:%s' has no "
-                   "namespace binding in scope in the stylesheet; "
-                   "this is an error, since the namespace was not "
-                   "specified by the instruction itself.\n", prefix, name);
-           }
+            xsltTransformError(ctxt, NULL, inst,
+                "xsl:element: The QName '%s:%s' has no "
+                "namespace binding in scope in the stylesheet; "
+                "this is an error, since the namespace was not "
+                "specified by the instruction itself.\n", prefix, name);
        } else
            nsName = ns->href;
     }
@@ -4070,7 +4072,17 @@ xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
     * Find/create a matching ns-decl in the result tree.
     */
     if (nsName != NULL) {
-       copy->ns = xsltGetSpecialNamespace(ctxt, inst, nsName, prefix, copy);
+       if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
+            /* Don't use a prefix of "xmlns" */
+           xmlChar *pref = xmlStrdup(BAD_CAST "ns_1");
+
+           copy->ns = xsltGetSpecialNamespace(ctxt, inst, nsName, pref, copy);
+
+           xmlFree(pref);
+       } else {
+           copy->ns = xsltGetSpecialNamespace(ctxt, inst, nsName, prefix,
+               copy);
+       }
     } else if ((copy->parent != NULL) &&
        (copy->parent->type == XML_ELEMENT_NODE) &&
        (copy->parent->ns != NULL))
@@ -4427,7 +4439,6 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
     xsltStylePreCompPtr comp = castedComp;
 #endif
     xmlXPathObjectPtr res = NULL;
-    xmlNodePtr copy = NULL;
     xmlChar *value = NULL;
     xmlDocPtr oldXPContextDoc;
     xmlNsPtr *oldXPNamespaces;
@@ -4500,8 +4511,7 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
            goto error;
        }
        if (value[0] != 0) {
-           copy = xsltCopyTextString(ctxt,
-               ctxt->insert, value, comp->noescape);
+           xsltCopyTextString(ctxt, ctxt->insert, value, comp->noescape);
        }
     } else {
        xsltTransformError(ctxt, NULL, inst,
diff --git a/tests/docs/bug-177.xml b/tests/docs/bug-177.xml
new file mode 100644 (file)
index 0000000..69d62f2
--- /dev/null
@@ -0,0 +1 @@
+<doc/>
index c9b2036..e531870 100644 (file)
@@ -184,6 +184,7 @@ EXTRA_DIST = \
     bug-174.out bug-174.xsl bug-174.err \
     bug-175.out bug-175.xsl bug-175.err \
     bug-176.out bug-176.xsl \
+    bug-177.out bug-177.xsl \
     bug-178.out bug-178.xsl \
     character.out character.xsl \
     character2.out character2.xsl \
diff --git a/tests/general/bug-177.out b/tests/general/bug-177.out
new file mode 100644 (file)
index 0000000..91cd684
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<doc xml:id="etc"/>
diff --git a/tests/general/bug-177.xsl b/tests/general/bug-177.xsl
new file mode 100644 (file)
index 0000000..52036f5
--- /dev/null
@@ -0,0 +1,7 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+    <xsl:template match="/*">
+        <xsl:copy>
+            <xsl:attribute name="id" namespace="http://www.w3.org/XML/1998/namespace">etc</xsl:attribute>
+        </xsl:copy>
+    </xsl:template>
+</xsl:stylesheet>