]> granicus.if.org Git - php/commitdiff
fix crash passing non-string member to sxe_prop_dim_exists
authorRob Richards <rrichards@php.net>
Sun, 5 Mar 2006 14:01:13 +0000 (14:01 +0000)
committerRob Richards <rrichards@php.net>
Sun, 5 Mar 2006 14:01:13 +0000 (14:01 +0000)
allow offsets to be used when calling isset/unset
fix tests
add test

ext/simplexml/simplexml.c
ext/simplexml/tests/027.phpt
ext/simplexml/tests/030.phpt [new file with mode: 0644]
ext/simplexml/tests/bug35785.phpt

index e51b7ba9f6fc7da51b141f3b17a559b8cf57b1c0..3b23eee7fa70d8556cd846c2e7526d799e95c161 100644 (file)
@@ -626,6 +626,14 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend
        xmlAttrPtr      attr = NULL;
        int                             exists = 0;
        int             test = 0;
+       zval            tmp_zv;
+
+       if (Z_TYPE_P(member) != IS_STRING && Z_TYPE_P(member) != IS_LONG) {
+               tmp_zv = *member;
+               zval_copy_ctor(&tmp_zv);
+               member = &tmp_zv;
+               convert_to_string(member);
+       }
 
        sxe = php_sxe_fetch_object(object TSRMLS_CC);
 
@@ -655,13 +663,28 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend
 
        if (node) {
                if (attribs) {
-                       while (attr) {
-                               if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) {
-                                       exists = 1;
-                                       break;
+                       if (Z_TYPE_P(member) == IS_LONG) {
+                               int     nodendx = 0;
+
+                               while (attr && nodendx <= Z_LVAL_P(member)) {
+                                       if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) {
+                                               if (nodendx == Z_LVAL_P(member)) {
+                                                       exists = 1;
+                                                       break;
+                                               }
+                                               nodendx++;
+                                       }
+                                       attr = attr->next;
                                }
+                       } else {
+                               while (attr) {
+                                       if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) {
+                                               exists = 1;
+                                               break;
+                                       }
 
-                               attr = attr->next;
+                                       attr = attr->next;
+                               }
                        }
                }
 
@@ -673,14 +696,6 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend
                                node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL);
                        }
                        else {
-                               zval tmp_zv;
-
-                               if (Z_TYPE_P(member) != IS_STRING) {
-                                       tmp_zv = *member;
-                                       zval_copy_ctor(&tmp_zv);
-                                       member = &tmp_zv;
-                                       convert_to_string(member);
-                               }
                                node = node->children;
                                while (node) {
                                        xmlNodePtr nnext;
@@ -690,9 +705,6 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend
                                        }
                                        node = nnext;
                                }
-                               if (member == &tmp_zv) {
-                                       zval_dtor(&tmp_zv);
-                               }
                        }
                        if (node) {
                                exists = 1;
@@ -700,6 +712,10 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend
                }
        }
 
+       if (member == &tmp_zv) {
+               zval_dtor(&tmp_zv);
+       }
+
        return exists;
 }
 /* }}} */
@@ -732,7 +748,7 @@ static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements,
        zval            tmp_zv;
        int             test;
 
-       if (Z_TYPE_P(member) != IS_STRING) {
+       if (Z_TYPE_P(member) != IS_STRING && Z_TYPE_P(member) != IS_LONG) {
                tmp_zv = *member;
                zval_copy_ctor(&tmp_zv);
                member = &tmp_zv;
@@ -742,13 +758,24 @@ static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements,
        sxe = php_sxe_fetch_object(object TSRMLS_CC);
 
        GET_NODE(sxe, node);
+
+       if (Z_TYPE_P(member) == IS_LONG) {
+               if (sxe->iter.type != SXE_ITER_ATTRLIST) {
+                       attribs = 0;
+                       elements = 1;
+                       if (sxe->iter.type == SXE_ITER_CHILD) {
+                               node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
+                       }
+               }
+       }
+
        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                attribs = 1;
                elements = 0;           
                node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                attr = (xmlAttrPtr)node;
                test = sxe->iter.name != NULL;
-       } else {
+       } else if (sxe->iter.type != SXE_ITER_CHILD) {
                node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                attr = node ? node->properties : NULL;
                test = 0;
@@ -756,31 +783,58 @@ static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements,
 
        if (node) {
                if (attribs) {
-                       while (attr) {
-                               anext = attr->next;
-                               if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) {
-                                       xmlUnlinkNode((xmlNodePtr) attr);
-                                       php_libxml_node_free_resource((xmlNodePtr) attr TSRMLS_CC);
-                                       break;
+                       if (Z_TYPE_P(member) == IS_LONG) {
+                               int     nodendx = 0;
+
+                               while (attr && nodendx <= Z_LVAL_P(member)) {
+                                       if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) {
+                                               if (nodendx == Z_LVAL_P(member)) {
+                                                       xmlUnlinkNode((xmlNodePtr) attr);
+                                                       php_libxml_node_free_resource((xmlNodePtr) attr TSRMLS_CC);
+                                                       break;
+                                               }
+                                               nodendx++;
+                                       }
+                                       attr = attr->next;
+                               }
+                       } else {
+                               while (attr) {
+                                       anext = attr->next;
+                                       if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) {
+                                               xmlUnlinkNode((xmlNodePtr) attr);
+                                               php_libxml_node_free_resource((xmlNodePtr) attr TSRMLS_CC);
+                                               break;
+                                       }
+                                       attr = anext;
                                }
-                               attr = anext;
                        }
                }
 
                if (elements) {
-                       node = node->children;
-                       while (node) {
-                               nnext = node->next;
-
-                               SKIP_TEXT(node);
-
-                               if (!xmlStrcmp(node->name, Z_STRVAL_P(member))) {
+                       if (Z_TYPE_P(member) == IS_LONG) {
+                               if (sxe->iter.type == SXE_ITER_CHILD) {
+                                       node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
+                               }
+                               node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL);
+                               if (node) {
                                        xmlUnlinkNode(node);
                                        php_libxml_node_free_resource(node TSRMLS_CC);
                                }
+                       } else {
+                               node = node->children;
+                               while (node) {
+                                       nnext = node->next;
+
+                                       SKIP_TEXT(node);
+
+                                       if (!xmlStrcmp(node->name, Z_STRVAL_P(member))) {
+                                               xmlUnlinkNode(node);
+                                               php_libxml_node_free_resource(node TSRMLS_CC);
+                                       }
 
 next_iter:
-                               node = nnext;
+                                       node = nnext;
+                               }
                        }
                }
        }
index 0c8f4e28474a5a2ae3ecae1d83fc55fae552f11e..f32786c7cc296d642e54cc5004f3ca0cf252cd1f 100755 (executable)
@@ -61,7 +61,7 @@ $people->person[3]['gender'] = 'error';
   </person>
 </people>
 
-Warning: main(): Cannot add element person number 3 when only 2 such elements exist in %sext/simplexml/tests/027.php on line %d
+Warning: main(): Cannot add element person number 3 when only 2 such elements exist in %s027.php on line %d
 <people>
   <person gender="female">Jane
   </person>
@@ -71,4 +71,4 @@ Warning: main(): Cannot add element person number 3 when only 2 such elements ex
   </person>
 </people>
 
-Fatal error: Objects used as arrays in post/pre increment/decrement must return values by reference in %sext/simplexml/tests/027.php on line %d
+Fatal error: Objects used as arrays in post/pre increment/decrement must return values by reference in %s027.php on line %d
diff --git a/ext/simplexml/tests/030.phpt b/ext/simplexml/tests/030.phpt
new file mode 100644 (file)
index 0000000..774a5f1
--- /dev/null
@@ -0,0 +1,44 @@
+--TEST--
+SimpleXML: isset and unset by offset
+--SKIPIF--
+<?php if (!extension_loaded("simplexml")) print "skip"; ?>
+--FILE--
+<?php 
+$xml =<<<EOF
+<root s:att1="b" att1="a" 
+      xmlns:s="urn::test" xmlns:t="urn::test-t">
+   <child1>test</child1>
+   <child1>test 2</child1>
+   <s:child3 />
+</root>
+EOF;
+
+$sxe = simplexml_load_string($xml);
+
+echo $sxe->child1[0]."\n";
+echo $sxe->child1[1]."\n\n";
+
+var_dump(isset($sxe->child1[1]));
+unset($sxe->child1[1]);
+var_dump(isset($sxe->child1[1]));
+echo "\n";
+
+$atts = $sxe->attributes("urn::test");
+var_dump(isset($atts[0]));
+unset($atts[0]);
+var_dump(isset($atts[0]));
+var_dump(isset($atts[TRUE]));
+
+?>
+===DONE===
+--EXPECT--
+test
+test 2
+
+bool(true)
+bool(false)
+
+bool(true)
+bool(false)
+bool(false)
+===DONE===
index fb3cea231f40b4ec31e0daea94d47309babe5c13..de65a19565b6b670eecc799dcbdc2c25f92a2cc9 100755 (executable)
@@ -23,4 +23,4 @@ echo $xml->asXML();
 ===FAIL===
 int(0)
 
-Fatal error: Objects used as arrays in post/pre increment/decrement must return values by reference in %sext/simplexml/tests/bug35785.php on line %d
+Fatal error: Objects used as arrays in post/pre increment/decrement must return values by reference in %sbug35785.php on line %d