From: Rob Richards Date: Sun, 5 Mar 2006 14:01:13 +0000 (+0000) Subject: fix crash passing non-string member to sxe_prop_dim_exists X-Git-Tag: RELEASE_1_3~544 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6c2c57e2bd6278a36c4b210e72e2847e1dec4f9e;p=php fix crash passing non-string member to sxe_prop_dim_exists allow offsets to be used when calling isset/unset fix tests add test --- diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index e51b7ba9f6..3b23eee7fa 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -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; + } } } } diff --git a/ext/simplexml/tests/027.phpt b/ext/simplexml/tests/027.phpt index 0c8f4e2847..f32786c7cc 100755 --- a/ext/simplexml/tests/027.phpt +++ b/ext/simplexml/tests/027.phpt @@ -61,7 +61,7 @@ $people->person[3]['gender'] = 'error'; -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 Jane @@ -71,4 +71,4 @@ Warning: main(): Cannot add element person number 3 when only 2 such elements ex -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 index 0000000000..774a5f1459 --- /dev/null +++ b/ext/simplexml/tests/030.phpt @@ -0,0 +1,44 @@ +--TEST-- +SimpleXML: isset and unset by offset +--SKIPIF-- + +--FILE-- + + test + test 2 + + +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=== diff --git a/ext/simplexml/tests/bug35785.phpt b/ext/simplexml/tests/bug35785.phpt index fb3cea231f..de65a19565 100755 --- a/ext/simplexml/tests/bug35785.phpt +++ b/ext/simplexml/tests/bug35785.phpt @@ -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