[7/7] msxml3: Prevent loop creation in IXMLDOMNode::replaceChild

Michael Karcher wine at mkarcher.dialup.fu-berlin.de
Sun Oct 5 05:13:59 CDT 2008


Tested on Windows XP and Wine
---
 dlls/msxml3/node.c         |   21 +++++++++++++++++----
 dlls/msxml3/tests/domdoc.c |   13 +++++++++++--
 2 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c
index 93166d5..62e13cb 100644
--- a/dlls/msxml3/node.c
+++ b/dlls/msxml3/node.c
@@ -610,7 +610,8 @@ static HRESULT WINAPI xmlnode_replaceChild(
     IXMLDOMNode** outOldChild)
 {
     xmlnode *This = impl_from_IXMLDOMNode( iface );
-    xmlNode *child_node_ptr;
+    xmlNode *old_child_ptr, *new_child_ptr;
+    xmlNode *my_ancestor;
 
     TRACE("%p->(%p,%p,%p)\n",This,newChild,oldChild,outOldChild);
     
@@ -622,14 +623,26 @@ static HRESULT WINAPI xmlnode_replaceChild(
     if(outOldChild)
         *outOldChild = NULL;
 
-    child_node_ptr = impl_from_IXMLDOMNode(oldChild)->node;
-    if(child_node_ptr->parent != This->node)
+    old_child_ptr = impl_from_IXMLDOMNode(oldChild)->node;
+    if(old_child_ptr->parent != This->node)
     {
         WARN("childNode %p is not a child of %p\n", oldChild, iface);
         return E_INVALIDARG;
     }
+    
+    new_child_ptr = impl_from_IXMLDOMNode(newChild)->node;
+    my_ancestor = This->node;
+    while(my_ancestor)
+    {
+        if(my_ancestor == new_child_ptr)
+        {
+            WARN("tried to create loop\n");
+            return E_FAIL;
+        }
+        my_ancestor = my_ancestor->parent;
+    }
 
-    xmlReplaceNode(child_node_ptr, impl_from_IXMLDOMNode(newChild)->node);
+    xmlReplaceNode(old_child_ptr, impl_from_IXMLDOMNode(newChild)->node);
 
     if(outOldChild)
     {
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index c29471e..891b166 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -1842,7 +1842,7 @@ static void test_replaceChild(void)
     VARIANT_BOOL b;
     IXMLDOMDocument *doc;
     IXMLDOMElement *element;
-    IXMLDOMNode *fo_node, *ba_node, *removed_node, *temp_node;
+    IXMLDOMNode *fo_node, *ba_node, *lc_node, *removed_node, *temp_node;
     IXMLDOMNodeList *root_list, *fo_list;
     IUnknown * unk1, *unk2;
     long len;
@@ -1864,6 +1864,9 @@ static void test_replaceChild(void)
     r = IXMLDOMElement_get_childNodes( element, &root_list );
     ok( r == S_OK, "ret %08x\n", r);
 
+    r = IXMLDOMNodeList_get_item( root_list, 0, &lc_node );
+    ok( r == S_OK, "ret %08x\n", r);
+ 
     r = IXMLDOMNodeList_get_item( root_list, 3, &fo_node );
     ok( r == S_OK, "ret %08x\n", r);
  
@@ -1889,10 +1892,16 @@ static void test_replaceChild(void)
 
     /* invalid parameter: OldNode is not a child */
     removed_node = (void*)0xdeadbeef;
-    r = IXMLDOMElement_replaceChild( element, ba_node, ba_node, &removed_node );
+    r = IXMLDOMElement_replaceChild( element, lc_node, ba_node, &removed_node );
     ok( r == E_INVALIDARG, "ret %08x\n", r );
     ok( removed_node == NULL, "%p\n", removed_node );
 
+    /* invalid parameter: would create loop */
+    removed_node = (void*)0xdeadbeef;
+    r = IXMLDOMNode_replaceChild( fo_node, fo_node, ba_node, &removed_node );
+    ok( r == E_FAIL, "ret %08x\n", r );
+    ok( removed_node == NULL, "%p\n", removed_node );
+
     r = IXMLDOMElement_replaceChild( element, ba_node, fo_node, NULL );
     ok( r == S_OK, "ret %08x\n", r );
     
-- 
1.5.6.5




More information about the wine-patches mailing list