File perl-XML-LibXML-CVE-2017-10672.patch of Package perl-XML-LibXML.6154

Index: XML-LibXML-2.0019/LibXML.xs
===================================================================
--- XML-LibXML-2.0019.orig/LibXML.xs
+++ XML-LibXML-2.0019/LibXML.xs
@@ -1008,6 +1008,40 @@ LibXML_test_node_name( xmlChar * name )
     return(1);
 }
 
+/* Assumes that the node has a proxy. */
+static void
+LibXML_reparent_removed_node(xmlNodePtr node) {
+    /*
+     * Attribute nodes can't be added to document fragments. Adding
+    * DTD nodes would cause a memory leak. So document and owner are
+     * set to NULL.
+     */
+    if (node->type != XML_ATTRIBUTE_NODE
+        && node->type != XML_DTD_NODE) {
+        ProxyNodePtr docfrag = PmmNewFragment(node->doc);
+        xmlAddChild(PmmNODE(docfrag), node);
+        PmmFixOwner(PmmPROXYNODE(node), docfrag);
+    }
+}
+
+static void
+LibXML_set_int_subset(xmlDocPtr doc, xmlNodePtr dtd) {
+    xmlNodePtr old_dtd = (xmlNodePtr)doc->intSubset;
+    if (old_dtd == dtd) {
+        return;
+    }
+
+    if (old_dtd != NULL) {
+        xmlUnlinkNode(old_dtd);
+
+        if (PmmPROXYNODE(old_dtd) == NULL) {
+            xmlFreeDtd((xmlDtdPtr)old_dtd);
+        }
+    }
+
+    doc->intSubset = (xmlDtdPtr)dtd;
+}
+
 /* ****************************************************************
  * XPathContext helper functions
  * **************************************************************** */
@@ -4689,42 +4723,47 @@ replaceChild( self, nNode, oNode )
         xmlNodePtr oNode
     PREINIT:
         xmlNodePtr ret = NULL;
-        ProxyNodePtr docfrag = NULL;
     CODE:
-       if ( self->type == XML_DOCUMENT_NODE ) {
-                switch ( nNode->type ) {
-                case XML_ELEMENT_NODE:
-                    warn("replaceChild with an element on a document node not supported yet!");
-                    XSRETURN_UNDEF;
-                    break;
-                case XML_DOCUMENT_FRAG_NODE:
-                    warn("replaceChild with a document fragment node on a document node not supported yet!");
-                    XSRETURN_UNDEF;
-                    break;
-                case XML_TEXT_NODE:
-                case XML_CDATA_SECTION_NODE:
-                    warn("replaceChild with a text node not supported on a document node!");
-                    XSRETURN_UNDEF;
-                    break;
-                default:
-                    break;
+        // if newNode == oldNode or self == newNode then do nothing, just return nNode.
+        if(nNode == oNode || self == nNode ){ 
+		ret = nNode;
+		RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
+        }
+        else{
+            if ( self->type == XML_DOCUMENT_NODE ) {
+                    switch ( nNode->type ) {
+                    case XML_ELEMENT_NODE:
+                        warn("replaceChild with an element on a document node not supported yet!");
+                        XSRETURN_UNDEF;
+                        break;
+                    case XML_DOCUMENT_FRAG_NODE:
+                        warn("replaceChild with a document fragment node on a document node not supported yet!");
+                        XSRETURN_UNDEF;
+                        break;
+                    case XML_TEXT_NODE:
+                    case XML_CDATA_SECTION_NODE:
+                        warn("replaceChild with a text node not supported on a document node!");
+                        XSRETURN_UNDEF;
+                        break;
+                    default:
+                        break;
+                    }
+            }
+            ret = domReplaceChild( self, nNode, oNode );
+            if (ret == NULL) {
+                XSRETURN_UNDEF;
+            }
+            else {
+                LibXML_reparent_removed_node(ret);
+                RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
+                if (nNode->type == XML_DTD_NODE) {
+                    LibXML_set_int_subset(nNode->doc, nNode);
                 }
-        }
-        ret = domReplaceChild( self, nNode, oNode );
-        if (ret == NULL) {
-            XSRETURN_UNDEF;
-        }
-        else {
-                docfrag = PmmNewFragment( self->doc );
-                /* create document fragment */
-                xmlAddChild( PmmNODE(docfrag), ret );
-                RETVAL = PmmNodeToSv(ret, docfrag);
-
                 if ( nNode->_private != NULL ) {
                     PmmFixOwner( PmmPROXYNODE(nNode),
                                  PmmOWNERPO(PmmPROXYNODE(self)) );
                 }
-                PmmFixOwner( SvPROXYNODE(RETVAL), docfrag );
+            }
         }
     OUTPUT:
         RETVAL
Index: XML-LibXML-2.0019/dom.c
===================================================================
--- XML-LibXML-2.0019.orig/dom.c
+++ XML-LibXML-2.0019/dom.c
@@ -794,7 +794,7 @@ domReplaceChild( xmlNodePtr self, xmlNod
         return NULL;
 
     if ( new == old )
-        return new;
+        return NULL;
 
     if ( new == NULL ) {
         /* level2 sais nothing about this case :( */
Index: XML-LibXML-2.0019/t/ufa.t
===================================================================
--- /dev/null
+++ XML-LibXML-2.0019/t/ufa.t
@@ -0,0 +1,12 @@
+use Test::More;
+use XML::LibXML;
+
+#test bug use after free in function replaceChild
+BEGIN { $| = 1 }
+my $data='<mipu94><pwn4fun><ufanode>-------------------------------------------------------tadinhsung-at-gmail-dot-com-----------------------------------------------------</ufanode></pwn4fun></mipu94>';
+my $parser = XML::LibXML->new();
+my $info = $parser->load_xml(string=>$data) or die;
+my $root = $info->findnodes("mipu94")->[0];
+my $ufanode = $root->findnodes("pwn4fun/ufanode")->[0];
+ok($root->replaceChild($ufanode,$ufanode),"Test UFA in replaceChild");
+done_testing();
openSUSE Build Service is sponsored by