@@ -45,6 +45,7 @@ PHP_SXE_API zend_class_entry *sxe_get_element_class_entry(void) /* {{{ */
4545
4646static php_sxe_object * php_sxe_object_new (zend_class_entry * ce , zend_function * fptr_count );
4747static xmlNodePtr php_sxe_reset_iterator (php_sxe_object * sxe , int use_data );
48+ static xmlNodePtr php_sxe_reset_iterator_no_clear_iter_data (php_sxe_object * sxe , int use_data );
4849static xmlNodePtr php_sxe_iterator_fetch (php_sxe_object * sxe , xmlNodePtr node , int use_data );
4950static void php_sxe_iterator_dtor (zend_object_iterator * iter );
5051static int php_sxe_iterator_valid (zend_object_iterator * iter );
@@ -77,6 +78,7 @@ static void _node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value, SXE
7778}
7879/* }}} */
7980
81+ /* Important: this overwrites the iterator data, if you wish to keep it use php_sxe_get_first_node_non_destructive() instead! */
8082static xmlNodePtr php_sxe_get_first_node (php_sxe_object * sxe , xmlNodePtr node ) /* {{{ */
8183{
8284 php_sxe_object * intern ;
@@ -95,6 +97,15 @@ static xmlNodePtr php_sxe_get_first_node(php_sxe_object *sxe, xmlNodePtr node) /
9597}
9698/* }}} */
9799
100+ static xmlNodePtr php_sxe_get_first_node_non_destructive (php_sxe_object * sxe , xmlNodePtr node )
101+ {
102+ if (sxe && sxe -> iter .type != SXE_ITER_NONE ) {
103+ return php_sxe_reset_iterator_no_clear_iter_data (sxe , false);
104+ } else {
105+ return node ;
106+ }
107+ }
108+
98109static inline int match_ns (php_sxe_object * sxe , xmlNodePtr node , xmlChar * name , int prefix ) /* {{{ */
99110{
100111 if (name == NULL && (node -> ns == NULL || node -> ns -> prefix == NULL )) {
@@ -1186,6 +1197,12 @@ static HashTable *sxe_get_prop_hash(zend_object *object, int is_debug) /* {{{ */
11861197 sxe_properties_add (rv , name , namelen , & value );
11871198 }
11881199next_iter :
1200+ if (UNEXPECTED (node -> type == XML_ENTITY_DECL )) {
1201+ /* Entity decls are linked together via the next pointer.
1202+ * The only way to get to an entity decl is via an entity reference in the document.
1203+ * If we then continue iterating, we'll end up in the DTD. Even worse, if the entities reference each other we'll infinite loop. */
1204+ break ;
1205+ }
11891206 if (use_iter ) {
11901207 node = php_sxe_iterator_fetch (sxe , node -> next , 0 );
11911208 } else {
@@ -1625,7 +1642,7 @@ PHP_METHOD(SimpleXMLElement, getName)
16251642 sxe = Z_SXEOBJ_P (ZEND_THIS );
16261643
16271644 GET_NODE (sxe , node );
1628- node = php_sxe_get_first_node (sxe , node );
1645+ node = php_sxe_get_first_node_non_destructive (sxe , node );
16291646 if (node ) {
16301647 namelen = xmlStrlen (node -> name );
16311648 RETURN_STRINGL ((char * )node -> name , namelen );
@@ -2450,15 +2467,9 @@ static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, i
24502467}
24512468/* }}} */
24522469
2453- static xmlNodePtr php_sxe_reset_iterator (php_sxe_object * sxe , int use_data ) /* {{{ */
2470+ static xmlNodePtr php_sxe_reset_iterator_no_clear_iter_data (php_sxe_object * sxe , int use_data )
24542471{
24552472 xmlNodePtr node ;
2456-
2457- if (!Z_ISUNDEF (sxe -> iter .data )) {
2458- zval_ptr_dtor (& sxe -> iter .data );
2459- ZVAL_UNDEF (& sxe -> iter .data );
2460- }
2461-
24622473 GET_NODE (sxe , node )
24632474
24642475 if (node ) {
@@ -2471,10 +2482,23 @@ static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data) /* {
24712482 case SXE_ITER_ATTRLIST :
24722483 node = (xmlNodePtr ) node -> properties ;
24732484 }
2485+ if (use_data ) {
2486+ ZEND_ASSERT (Z_ISUNDEF (sxe -> iter .data ));
2487+ }
24742488 return php_sxe_iterator_fetch (sxe , node , use_data );
24752489 }
24762490 return NULL ;
24772491}
2492+
2493+ static xmlNodePtr php_sxe_reset_iterator (php_sxe_object * sxe , int use_data ) /* {{{ */
2494+ {
2495+ if (!Z_ISUNDEF (sxe -> iter .data )) {
2496+ zval_ptr_dtor (& sxe -> iter .data );
2497+ ZVAL_UNDEF (& sxe -> iter .data );
2498+ }
2499+
2500+ return php_sxe_reset_iterator_no_clear_iter_data (sxe , use_data );
2501+ }
24782502/* }}} */
24792503
24802504zend_object_iterator * php_sxe_get_iterator (zend_class_entry * ce , zval * object , int by_ref ) /* {{{ */
0 commit comments