From 4b9fbc6627cc17869fb43826e30299f6e716178b Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 4 Nov 2021 10:34:52 +0100 Subject: [PATCH] Fixed bug #81587 iterator_funcs_ptr may be null for Iterators with custom get_iterator. Ideally MultipleIterator would make use of get_iterator, but this would require a large implementation change. --- NEWS | 4 ++++ ext/spl/spl_observer.c | 12 ++++++------ ext/spl/tests/bug81587.phpt | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 ext/spl/tests/bug81587.phpt diff --git a/NEWS b/NEWS index 7409abddc8c..14b68d91b68 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2021, PHP 8.0.14 +- SPL: + . Fixed bug #81587 (MultipleIterator Segmentation fault w/ SimpleXMLElement + attached). (Nikita) + 18 Nov 2021, PHP 8.0.13 - Core: diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 3f134b77dba..16c1c3c97e5 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -1029,7 +1029,7 @@ PHP_METHOD(MultipleIterator, rewind) zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { it = &element->obj; - zend_call_method_with_0_params(Z_OBJ_P(it), Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_rewind, "rewind", NULL); + zend_call_method_with_0_params(Z_OBJ_P(it), Z_OBJCE_P(it), Z_OBJCE_P(it)->iterator_funcs_ptr ? &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_rewind : NULL, "rewind", NULL); zend_hash_move_forward_ex(&intern->storage, &intern->pos); } } @@ -1051,7 +1051,7 @@ PHP_METHOD(MultipleIterator, next) zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { it = &element->obj; - zend_call_method_with_0_params(Z_OBJ_P(it), Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_next, "next", NULL); + zend_call_method_with_0_params(Z_OBJ_P(it), Z_OBJCE_P(it), Z_OBJCE_P(it)->iterator_funcs_ptr ? &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_next : NULL, "next", NULL); zend_hash_move_forward_ex(&intern->storage, &intern->pos); } } @@ -1080,7 +1080,7 @@ PHP_METHOD(MultipleIterator, valid) zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { it = &element->obj; - zend_call_method_with_0_params(Z_OBJ_P(it), Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_valid, "valid", &retval); + zend_call_method_with_0_params(Z_OBJ_P(it), Z_OBJCE_P(it), Z_OBJCE_P(it)->iterator_funcs_ptr ? &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_valid : NULL, "valid", &retval); if (!Z_ISUNDEF(retval)) { valid = (Z_TYPE(retval) == IS_TRUE); @@ -1116,7 +1116,7 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_ zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { it = &element->obj; - zend_call_method_with_0_params(Z_OBJ_P(it), Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_valid, "valid", &retval); + zend_call_method_with_0_params(Z_OBJ_P(it), Z_OBJCE_P(it), Z_OBJCE_P(it)->iterator_funcs_ptr ? &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_valid : NULL, "valid", &retval); if (!Z_ISUNDEF(retval)) { valid = Z_TYPE(retval) == IS_TRUE; @@ -1127,9 +1127,9 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_ if (valid) { if (SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT == get_type) { - zend_call_method_with_0_params(Z_OBJ_P(it), Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_current, "current", &retval); + zend_call_method_with_0_params(Z_OBJ_P(it), Z_OBJCE_P(it), Z_OBJCE_P(it)->iterator_funcs_ptr ? &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_current : NULL, "current", &retval); } else { - zend_call_method_with_0_params(Z_OBJ_P(it), Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_key, "key", &retval); + zend_call_method_with_0_params(Z_OBJ_P(it), Z_OBJCE_P(it), Z_OBJCE_P(it)->iterator_funcs_ptr ? &Z_OBJCE_P(it)->iterator_funcs_ptr->zf_key : NULL, "key", &retval); } if (Z_ISUNDEF(retval)) { zend_throw_exception(spl_ce_RuntimeException, "Failed to call sub iterator method", 0); diff --git a/ext/spl/tests/bug81587.phpt b/ext/spl/tests/bug81587.phpt new file mode 100644 index 00000000000..89bb104bb4a --- /dev/null +++ b/ext/spl/tests/bug81587.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #81587: MultipleIterator Segmentation fault w/ SimpleXMLElement attached +--SKIPIF-- + +--FILE-- +attachIterator(new SimpleXMLElement('')); +foreach ($mi as $v) { + var_dump($v); +} +?> +--EXPECT-- +array(1) { + [0]=> + object(SimpleXMLElement)#4 (0) { + } +}