diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 05bdfdb34ba3..a9cdfd124d82 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -531,6 +531,12 @@ static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce, static zend_result 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; + if (getiterator_cache && ((*getiterator_cache)->common.fn_flags & ZEND_ACC_ABSTRACT)) { + zend_throw_error(NULL, "Cannot call abstract method %s::%s()", + ZSTR_VAL((*getiterator_cache)->common.scope->name), + ZSTR_VAL((*getiterator_cache)->common.function_name)); + return FAILURE; + } zend_call_method_with_0_params(obj, ce, getiterator_cache, "getiterator", retval); if (EG(exception)) { return FAILURE; diff --git a/ext/spl/tests/gh25228.phpt b/ext/spl/tests/gh25228.phpt new file mode 100644 index 000000000000..bb43d764e971 --- /dev/null +++ b/ext/spl/tests/gh25228.phpt @@ -0,0 +1,42 @@ +--TEST-- +GH-25228 (Segfault in IteratorIterator::__construct() when $class is an abstract IteratorAggregate) +--FILE-- +getMessage(), "\n"; +} + +try { + new IteratorIterator(new D, 'C'); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +foreach (new IteratorIterator(new B, 'B') as $v) { + var_dump($v); +} + +?> +--EXPECT-- +Cannot call abstract method IteratorAggregate::getIterator() +Cannot call abstract method C::getIterator() +int(1)