mirror of
https://github.com/php/php-src.git
synced 2026-03-31 04:32:19 +02:00
Merge branch 'PHP-8.0'
* PHP-8.0: Fix RecursiveIteratorIterator segfault for invalid aggregate
This commit is contained in:
@@ -481,6 +481,24 @@ static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce,
|
||||
return (zend_object_iterator*)iterator;
|
||||
}
|
||||
|
||||
static int spl_get_iterator_from_aggregate(zval *retval, zend_class_entry *ce, zend_object *obj) {
|
||||
zend_function **getiterator_cache =
|
||||
ce->iterator_funcs_ptr ? &ce->iterator_funcs_ptr->zf_new_iterator : NULL;
|
||||
zend_call_method_with_0_params(obj, ce, getiterator_cache, "getiterator", retval);
|
||||
if (EG(exception)) {
|
||||
return FAILURE;
|
||||
}
|
||||
if (Z_TYPE_P(retval) != IS_OBJECT
|
||||
|| !instanceof_function(Z_OBJCE_P(retval), zend_ce_traversable)) {
|
||||
zend_throw_exception_ex(spl_ce_LogicException, 0,
|
||||
"%s::getIterator() must return an object that implements Traversable",
|
||||
ZSTR_VAL(ce->name));
|
||||
zval_ptr_dtor(retval);
|
||||
return FAILURE;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_base, zend_class_entry *ce_inner, recursive_it_it_type rit_type)
|
||||
{
|
||||
zval *object = ZEND_THIS;
|
||||
@@ -502,9 +520,10 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla
|
||||
}
|
||||
|
||||
if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate)) {
|
||||
zend_function **getiterator_cache = Z_OBJCE_P(iterator)->iterator_funcs_ptr
|
||||
? &Z_OBJCE_P(iterator)->iterator_funcs_ptr->zf_new_iterator : NULL;
|
||||
zend_call_method_with_0_params(Z_OBJ_P(iterator), Z_OBJCE_P(iterator), getiterator_cache, "getiterator", &aggregate_retval);
|
||||
if (spl_get_iterator_from_aggregate(
|
||||
&aggregate_retval, Z_OBJCE_P(iterator), Z_OBJ_P(iterator)) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
iterator = &aggregate_retval;
|
||||
} else {
|
||||
Z_ADDREF_P(iterator);
|
||||
@@ -526,9 +545,10 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla
|
||||
}
|
||||
|
||||
if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate)) {
|
||||
zend_function **getiterator_cache = Z_OBJCE_P(iterator)->iterator_funcs_ptr
|
||||
? &Z_OBJCE_P(iterator)->iterator_funcs_ptr->zf_new_iterator : NULL;
|
||||
zend_call_method_with_0_params(Z_OBJ_P(iterator), Z_OBJCE_P(iterator), getiterator_cache, "getiterator", &aggregate_retval);
|
||||
if (spl_get_iterator_from_aggregate(
|
||||
&aggregate_retval, Z_OBJCE_P(iterator), Z_OBJ_P(iterator)) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
iterator = &aggregate_retval;
|
||||
} else {
|
||||
Z_ADDREF_P(iterator);
|
||||
@@ -1332,15 +1352,7 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
|
||||
ce = ce_cast;
|
||||
}
|
||||
if (instanceof_function(ce, zend_ce_aggregate)) {
|
||||
zend_function **getiterator_cache =
|
||||
ce->iterator_funcs_ptr ? &ce->iterator_funcs_ptr->zf_new_iterator : NULL;
|
||||
zend_call_method_with_0_params(Z_OBJ_P(zobject), ce, getiterator_cache, "getiterator", &retval);
|
||||
if (EG(exception)) {
|
||||
zval_ptr_dtor(&retval);
|
||||
return NULL;
|
||||
}
|
||||
if (Z_TYPE(retval) != IS_OBJECT || !instanceof_function(Z_OBJCE(retval), zend_ce_traversable)) {
|
||||
zend_throw_exception_ex(spl_ce_LogicException, 0, "%s::getIterator() must return an object that implements Traversable", ZSTR_VAL(ce->name));
|
||||
if (spl_get_iterator_from_aggregate(&retval, ce, Z_OBJ_P(zobject)) == FAILURE) {
|
||||
return NULL;
|
||||
}
|
||||
zobject = &retval;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
RecursiveIteratorIterator constructor should thrown if IteratorAggregate does not return Iterator
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class MyIteratorAggregate implements IteratorAggregate {
|
||||
function getIterator() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
new RecursiveIteratorIterator(new MyIteratorAggregate);
|
||||
} catch (LogicException $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
MyIteratorAggregate::getIterator() must return an object that implements Traversable
|
||||
Reference in New Issue
Block a user