@@ -44,6 +44,7 @@ PHP_SXE_API zend_class_entry *sxe_get_element_class_entry(void) /* {{{ */
4444
4545static php_sxe_object * php_sxe_object_new (zend_class_entry * ce , zend_function * fptr_count );
4646static xmlNodePtr php_sxe_reset_iterator (php_sxe_object * sxe , int use_data );
47+ static xmlNodePtr php_sxe_reset_iterator_no_clear_iter_data (php_sxe_object * sxe , int use_data );
4748static xmlNodePtr php_sxe_iterator_fetch (php_sxe_object * sxe , xmlNodePtr node , int use_data );
4849static void php_sxe_iterator_dtor (zend_object_iterator * iter );
4950static int php_sxe_iterator_valid (zend_object_iterator * iter );
@@ -76,6 +77,7 @@ static void _node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value, SXE
7677}
7778/* }}} */
7879
80+ /* Important: this overwrites the iterator data, if you wish to keep it use php_sxe_get_first_node_non_destructive() instead! */
7981static xmlNodePtr php_sxe_get_first_node (php_sxe_object * sxe , xmlNodePtr node ) /* {{{ */
8082{
8183 php_sxe_object * intern ;
@@ -94,6 +96,15 @@ static xmlNodePtr php_sxe_get_first_node(php_sxe_object *sxe, xmlNodePtr node) /
9496}
9597/* }}} */
9698
99+ static xmlNodePtr php_sxe_get_first_node_non_destructive (php_sxe_object * sxe , xmlNodePtr node )
100+ {
101+ if (sxe && sxe -> iter .type != SXE_ITER_NONE ) {
102+ return php_sxe_reset_iterator_no_clear_iter_data (sxe , false);
103+ } else {
104+ return node ;
105+ }
106+ }
107+
97108static inline int match_ns (php_sxe_object * sxe , xmlNodePtr node , xmlChar * name , int prefix ) /* {{{ */
98109{
99110 if (name == NULL && (node -> ns == NULL || node -> ns -> prefix == NULL )) {
@@ -1177,6 +1188,12 @@ static HashTable *sxe_get_prop_hash(zend_object *object, int is_debug) /* {{{ */
11771188 sxe_properties_add (rv , name , namelen , & value );
11781189 }
11791190next_iter :
1191+ if (UNEXPECTED (node -> type == XML_ENTITY_DECL )) {
1192+ /* Entity decls are linked together via the next pointer.
1193+ * The only way to get to an entity decl is via an entity reference in the document.
1194+ * If we then continue iterating, we'll end up in the DTD. Even worse, if the entities reference each other we'll infinite loop. */
1195+ break ;
1196+ }
11801197 if (use_iter ) {
11811198 node = php_sxe_iterator_fetch (sxe , node -> next , 0 );
11821199 } else {
@@ -1616,7 +1633,7 @@ PHP_METHOD(SimpleXMLElement, getName)
16161633 sxe = Z_SXEOBJ_P (ZEND_THIS );
16171634
16181635 GET_NODE (sxe , node );
1619- node = php_sxe_get_first_node (sxe , node );
1636+ node = php_sxe_get_first_node_non_destructive (sxe , node );
16201637 if (node ) {
16211638 namelen = xmlStrlen (node -> name );
16221639 RETURN_STRINGL ((char * )node -> name , namelen );
@@ -2443,15 +2460,9 @@ static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, i
24432460}
24442461/* }}} */
24452462
2446- static xmlNodePtr php_sxe_reset_iterator (php_sxe_object * sxe , int use_data ) /* {{{ */
2463+ static xmlNodePtr php_sxe_reset_iterator_no_clear_iter_data (php_sxe_object * sxe , int use_data )
24472464{
24482465 xmlNodePtr node ;
2449-
2450- if (!Z_ISUNDEF (sxe -> iter .data )) {
2451- zval_ptr_dtor (& sxe -> iter .data );
2452- ZVAL_UNDEF (& sxe -> iter .data );
2453- }
2454-
24552466 GET_NODE (sxe , node )
24562467
24572468 if (node ) {
@@ -2464,10 +2475,23 @@ static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data) /* {
24642475 case SXE_ITER_ATTRLIST :
24652476 node = (xmlNodePtr ) node -> properties ;
24662477 }
2478+ if (use_data ) {
2479+ ZEND_ASSERT (Z_ISUNDEF (sxe -> iter .data ));
2480+ }
24672481 return php_sxe_iterator_fetch (sxe , node , use_data );
24682482 }
24692483 return NULL ;
24702484}
2485+
2486+ static xmlNodePtr php_sxe_reset_iterator (php_sxe_object * sxe , int use_data ) /* {{{ */
2487+ {
2488+ if (!Z_ISUNDEF (sxe -> iter .data )) {
2489+ zval_ptr_dtor (& sxe -> iter .data );
2490+ ZVAL_UNDEF (& sxe -> iter .data );
2491+ }
2492+
2493+ return php_sxe_reset_iterator_no_clear_iter_data (sxe , use_data );
2494+ }
24712495/* }}} */
24722496
24732497zend_object_iterator * php_sxe_get_iterator (zend_class_entry * ce , zval * object , int by_ref ) /* {{{ */
0 commit comments