Skip to content

Commit b842ea4

Browse files
committed
Apply SimpleXML iterator fixes only on master
Many methods in SimpleXML reset the iterator when called. This has the consequence that mixing these operations with loops can cause infinite loops, or the loss of iteration data. Some people may however rely on the resetting behaviour. To prevent unintended breaks in stable branches, let's only apply the fix to master. This reverts GH-12193, GH-12229, GG-12247 for stable branches while keeping them on master, adding a note in UPGRADING as well.
1 parent 1f5bea3 commit b842ea4

File tree

6 files changed

+33
-193
lines changed

6 files changed

+33
-193
lines changed

NEWS

-5
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,8 @@ PHP NEWS
3939

4040
- SimpleXML:
4141
. Fixed bug GH-12170 (Can't use xpath with comments in SimpleXML). (nielsdos)
42-
. Fixed bug GH-12192 (SimpleXML infinite loop when getName() is called
43-
within foreach). (nielsdos)
4442
. Fixed bug GH-12223 (Entity reference produces infinite loop in
4543
var_dump/print_r). (nielsdos)
46-
. Fixed bug GH-12208 (SimpleXML infinite loop when a cast is used inside a
47-
foreach). (nielsdos)
48-
. Fixed bug #55098 (SimpleXML iteration produces infinite loop). (nielsdos)
4944
. Fixed bug GH-12167 (Unable to get processing instruction contents in
5045
SimpleXML). (nielsdos)
5146
. Fixed bug GH-12169 (Unable to get comment contents in SimpleXML).

ext/simplexml/simplexml.c

+31-31
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ static void _node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value, SXE
7878
}
7979
/* }}} */
8080

81-
static xmlNodePtr php_sxe_get_first_node_non_destructive(php_sxe_object *sxe, xmlNodePtr node)
81+
static xmlNodePtr php_sxe_get_first_node(php_sxe_object *sxe, xmlNodePtr node)
8282
{
8383
if (sxe && sxe->iter.type != SXE_ITER_NONE) {
84-
return php_sxe_reset_iterator_no_clear_iter_data(sxe, false);
84+
return php_sxe_reset_iterator(sxe, 1);
8585
} else {
8686
return node;
8787
}
@@ -165,7 +165,7 @@ static xmlNodePtr sxe_get_element_by_name(php_sxe_object *sxe, xmlNodePtr node,
165165
if (sxe->iter.type == SXE_ITER_NONE) {
166166
sxe->iter.type = SXE_ITER_CHILD;
167167
}
168-
node = php_sxe_get_first_node_non_destructive(sxe, node);
168+
node = php_sxe_get_first_node(sxe, node);
169169
sxe->iter.type = orgtype;
170170
}
171171

@@ -251,11 +251,11 @@ static zval *sxe_prop_dim_read(zend_object *object, zval *member, bool elements,
251251
if (sxe->iter.type == SXE_ITER_ATTRLIST) {
252252
attribs = 1;
253253
elements = 0;
254-
node = php_sxe_get_first_node_non_destructive(sxe, node);
254+
node = php_sxe_get_first_node(sxe, node);
255255
attr = (xmlAttrPtr)node;
256256
test = sxe->iter.name != NULL;
257257
} else if (sxe->iter.type != SXE_ITER_CHILD) {
258-
node = php_sxe_get_first_node_non_destructive(sxe, node);
258+
node = php_sxe_get_first_node(sxe, node);
259259
attr = node ? node->properties : NULL;
260260
test = 0;
261261
if (!member && node && node->parent &&
@@ -303,7 +303,7 @@ static zval *sxe_prop_dim_read(zend_object *object, zval *member, bool elements,
303303
xmlNodePtr mynode = node;
304304

305305
if (sxe->iter.type == SXE_ITER_CHILD) {
306-
node = php_sxe_get_first_node_non_destructive(sxe, node);
306+
node = php_sxe_get_first_node(sxe, node);
307307
}
308308
if (sxe->iter.type == SXE_ITER_NONE) {
309309
if (member && Z_LVAL_P(member) > 0) {
@@ -437,12 +437,12 @@ static zval *sxe_prop_dim_write(zend_object *object, zval *member, zval *value,
437437
if (sxe->iter.type == SXE_ITER_ATTRLIST) {
438438
attribs = 1;
439439
elements = 0;
440-
node = php_sxe_get_first_node_non_destructive(sxe, node);
440+
node = php_sxe_get_first_node(sxe, node);
441441
attr = (xmlAttrPtr)node;
442442
test = sxe->iter.name != NULL;
443443
} else if (sxe->iter.type != SXE_ITER_CHILD) {
444444
mynode = node;
445-
node = php_sxe_get_first_node_non_destructive(sxe, node);
445+
node = php_sxe_get_first_node(sxe, node);
446446
attr = node ? node->properties : NULL;
447447
test = 0;
448448
if (!member && node && node->parent &&
@@ -688,19 +688,19 @@ static int sxe_prop_dim_exists(zend_object *object, zval *member, int check_empt
688688
attribs = 0;
689689
elements = 1;
690690
if (sxe->iter.type == SXE_ITER_CHILD) {
691-
node = php_sxe_get_first_node_non_destructive(sxe, node);
691+
node = php_sxe_get_first_node(sxe, node);
692692
}
693693
}
694694
}
695695

696696
if (sxe->iter.type == SXE_ITER_ATTRLIST) {
697697
attribs = 1;
698698
elements = 0;
699-
node = php_sxe_get_first_node_non_destructive(sxe, node);
699+
node = php_sxe_get_first_node(sxe, node);
700700
attr = (xmlAttrPtr)node;
701701
test = sxe->iter.name != NULL;
702702
} else if (sxe->iter.type != SXE_ITER_CHILD) {
703-
node = php_sxe_get_first_node_non_destructive(sxe, node);
703+
node = php_sxe_get_first_node(sxe, node);
704704
attr = node ? node->properties : NULL;
705705
test = 0;
706706
}
@@ -740,7 +740,7 @@ static int sxe_prop_dim_exists(zend_object *object, zval *member, int check_empt
740740
if (elements) {
741741
if (Z_TYPE_P(member) == IS_LONG) {
742742
if (sxe->iter.type == SXE_ITER_CHILD) {
743-
node = php_sxe_get_first_node_non_destructive(sxe, node);
743+
node = php_sxe_get_first_node(sxe, node);
744744
}
745745
node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL);
746746
} else {
@@ -810,19 +810,19 @@ static void sxe_prop_dim_delete(zend_object *object, zval *member, bool elements
810810
attribs = 0;
811811
elements = 1;
812812
if (sxe->iter.type == SXE_ITER_CHILD) {
813-
node = php_sxe_get_first_node_non_destructive(sxe, node);
813+
node = php_sxe_get_first_node(sxe, node);
814814
}
815815
}
816816
}
817817

818818
if (sxe->iter.type == SXE_ITER_ATTRLIST) {
819819
attribs = 1;
820820
elements = 0;
821-
node = php_sxe_get_first_node_non_destructive(sxe, node);
821+
node = php_sxe_get_first_node(sxe, node);
822822
attr = (xmlAttrPtr)node;
823823
test = sxe->iter.name != NULL;
824824
} else if (sxe->iter.type != SXE_ITER_CHILD) {
825-
node = php_sxe_get_first_node_non_destructive(sxe, node);
825+
node = php_sxe_get_first_node(sxe, node);
826826
attr = node ? node->properties : NULL;
827827
test = 0;
828828
}
@@ -859,7 +859,7 @@ static void sxe_prop_dim_delete(zend_object *object, zval *member, bool elements
859859
if (elements) {
860860
if (Z_TYPE_P(member) == IS_LONG) {
861861
if (sxe->iter.type == SXE_ITER_CHILD) {
862-
node = php_sxe_get_first_node_non_destructive(sxe, node);
862+
node = php_sxe_get_first_node(sxe, node);
863863
}
864864
node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL);
865865
if (node) {
@@ -992,7 +992,7 @@ static int sxe_prop_is_empty(zend_object *object) /* {{{ */
992992
}
993993

994994
if (sxe->iter.type == SXE_ITER_ELEMENT) {
995-
node = php_sxe_get_first_node_non_destructive(sxe, node);
995+
node = php_sxe_get_first_node(sxe, node);
996996
}
997997
if (!node || node->type != XML_ENTITY_DECL) {
998998
attr = node ? (xmlAttrPtr)node->properties : NULL;
@@ -1006,7 +1006,7 @@ static int sxe_prop_is_empty(zend_object *object) /* {{{ */
10061006
}
10071007

10081008
GET_NODE(sxe, node);
1009-
node = php_sxe_get_first_node_non_destructive(sxe, node);
1009+
node = php_sxe_get_first_node(sxe, node);
10101010
is_empty = 1;
10111011
ZVAL_UNDEF(&iter_data);
10121012
if (node && sxe->iter.type != SXE_ITER_ATTRLIST) {
@@ -1101,7 +1101,7 @@ static HashTable *sxe_get_prop_hash(zend_object *object, int is_debug) /* {{{ */
11011101
}
11021102
if (is_debug || sxe->iter.type != SXE_ITER_CHILD) {
11031103
if (sxe->iter.type == SXE_ITER_ELEMENT) {
1104-
node = php_sxe_get_first_node_non_destructive(sxe, node);
1104+
node = php_sxe_get_first_node(sxe, node);
11051105
}
11061106
if (!node || node->type != XML_ENTITY_DECL) {
11071107
attr = node ? (xmlAttrPtr)node->properties : NULL;
@@ -1123,7 +1123,7 @@ static HashTable *sxe_get_prop_hash(zend_object *object, int is_debug) /* {{{ */
11231123
}
11241124

11251125
GET_NODE(sxe, node);
1126-
node = php_sxe_get_first_node_non_destructive(sxe, node);
1126+
node = php_sxe_get_first_node(sxe, node);
11271127

11281128
if (node && sxe->iter.type != SXE_ITER_ATTRLIST) {
11291129
if (node->type == XML_ATTRIBUTE_NODE) {
@@ -1282,7 +1282,7 @@ PHP_METHOD(SimpleXMLElement, xpath)
12821282
}
12831283

12841284
GET_NODE(sxe, nodeptr);
1285-
nodeptr = php_sxe_get_first_node_non_destructive(sxe, nodeptr);
1285+
nodeptr = php_sxe_get_first_node(sxe, nodeptr);
12861286
if (!nodeptr) {
12871287
return;
12881288
}
@@ -1391,7 +1391,7 @@ PHP_METHOD(SimpleXMLElement, asXML)
13911391

13921392
sxe = Z_SXEOBJ_P(ZEND_THIS);
13931393
GET_NODE(sxe, node);
1394-
node = php_sxe_get_first_node_non_destructive(sxe, node);
1394+
node = php_sxe_get_first_node(sxe, node);
13951395

13961396
if (!node) {
13971397
RETURN_FALSE;
@@ -1514,7 +1514,7 @@ PHP_METHOD(SimpleXMLElement, getNamespaces)
15141514

15151515
sxe = Z_SXEOBJ_P(ZEND_THIS);
15161516
GET_NODE(sxe, node);
1517-
node = php_sxe_get_first_node_non_destructive(sxe, node);
1517+
node = php_sxe_get_first_node(sxe, node);
15181518

15191519
if (node) {
15201520
if (node->type == XML_ELEMENT_NODE) {
@@ -1599,7 +1599,7 @@ PHP_METHOD(SimpleXMLElement, children)
15991599
}
16001600

16011601
GET_NODE(sxe, node);
1602-
node = php_sxe_get_first_node_non_destructive(sxe, node);
1602+
node = php_sxe_get_first_node(sxe, node);
16031603
if (!node) {
16041604
return;
16051605
}
@@ -1623,7 +1623,7 @@ PHP_METHOD(SimpleXMLElement, getName)
16231623
sxe = Z_SXEOBJ_P(ZEND_THIS);
16241624

16251625
GET_NODE(sxe, node);
1626-
node = php_sxe_get_first_node_non_destructive(sxe, node);
1626+
node = php_sxe_get_first_node(sxe, node);
16271627
if (node) {
16281628
namelen = xmlStrlen(node->name);
16291629
RETURN_STRINGL((char*)node->name, namelen);
@@ -1648,7 +1648,7 @@ PHP_METHOD(SimpleXMLElement, attributes)
16481648

16491649
sxe = Z_SXEOBJ_P(ZEND_THIS);
16501650
GET_NODE(sxe, node);
1651-
node = php_sxe_get_first_node_non_destructive(sxe, node);
1651+
node = php_sxe_get_first_node(sxe, node);
16521652
if (!node) {
16531653
return;
16541654
}
@@ -1689,7 +1689,7 @@ PHP_METHOD(SimpleXMLElement, addChild)
16891689
return;
16901690
}
16911691

1692-
node = php_sxe_get_first_node_non_destructive(sxe, node);
1692+
node = php_sxe_get_first_node(sxe, node);
16931693

16941694
if (node == NULL) {
16951695
php_error_docref(NULL, E_WARNING, "Cannot add child. Parent is not a permanent member of the XML tree");
@@ -1749,7 +1749,7 @@ PHP_METHOD(SimpleXMLElement, addAttribute)
17491749
sxe = Z_SXEOBJ_P(ZEND_THIS);
17501750
GET_NODE(sxe, node);
17511751

1752-
node = php_sxe_get_first_node_non_destructive(sxe, node);
1752+
node = php_sxe_get_first_node(sxe, node);
17531753

17541754
if (node && node->type != XML_ELEMENT_NODE) {
17551755
node = node->parent;
@@ -1842,7 +1842,7 @@ static int sxe_object_cast_ex(zend_object *readobj, zval *writeobj, int type)
18421842
sxe = php_sxe_fetch_object(readobj);
18431843

18441844
if (type == _IS_BOOL) {
1845-
node = php_sxe_get_first_node_non_destructive(sxe, NULL);
1845+
node = php_sxe_get_first_node(sxe, NULL);
18461846
if (node) {
18471847
ZVAL_TRUE(writeobj);
18481848
} else {
@@ -1852,7 +1852,7 @@ static int sxe_object_cast_ex(zend_object *readobj, zval *writeobj, int type)
18521852
}
18531853

18541854
if (sxe->iter.type != SXE_ITER_NONE) {
1855-
node = php_sxe_get_first_node_non_destructive(sxe, NULL);
1855+
node = php_sxe_get_first_node(sxe, NULL);
18561856
if (node) {
18571857
contents = xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, node->children, 1);
18581858
}
@@ -2600,7 +2600,7 @@ void *simplexml_export_node(zval *object) /* {{{ */
26002600

26012601
sxe = Z_SXEOBJ_P(object);
26022602
GET_NODE(sxe, node);
2603-
return php_sxe_get_first_node_non_destructive(sxe, node);
2603+
return php_sxe_get_first_node(sxe, node);
26042604
}
26052605
/* }}} */
26062606

ext/simplexml/tests/bug55098.phpt

-92
This file was deleted.

ext/simplexml/tests/bug62639.phpt

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ foreach ($a2->b->c->children() as $key => $value) {
4141
var_dump($value);
4242
}?>
4343
--EXPECT--
44-
object(A)#4 (2) {
44+
object(A)#2 (2) {
4545
["@attributes"]=>
4646
array(1) {
4747
["attr"]=>
@@ -50,7 +50,7 @@ object(A)#4 (2) {
5050
[0]=>
5151
string(10) "Some Value"
5252
}
53-
object(A)#6 (2) {
53+
object(A)#3 (2) {
5454
["@attributes"]=>
5555
array(1) {
5656
["attr"]=>

0 commit comments

Comments
 (0)