@@ -481,6 +481,24 @@ static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce,
481
481
return (zend_object_iterator * )iterator ;
482
482
}
483
483
484
+ static int spl_get_iterator_from_aggregate (zval * retval , zend_class_entry * ce , zend_object * obj ) {
485
+ zend_function * * getiterator_cache =
486
+ ce -> iterator_funcs_ptr ? & ce -> iterator_funcs_ptr -> zf_new_iterator : NULL ;
487
+ zend_call_method_with_0_params (obj , ce , getiterator_cache , "getiterator" , retval );
488
+ if (EG (exception )) {
489
+ return FAILURE ;
490
+ }
491
+ if (Z_TYPE_P (retval ) != IS_OBJECT
492
+ || !instanceof_function (Z_OBJCE_P (retval ), zend_ce_traversable )) {
493
+ zend_throw_exception_ex (spl_ce_LogicException , 0 ,
494
+ "%s::getIterator() must return an object that implements Traversable" ,
495
+ ZSTR_VAL (ce -> name ));
496
+ zval_ptr_dtor (retval );
497
+ return FAILURE ;
498
+ }
499
+ return SUCCESS ;
500
+ }
501
+
484
502
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 )
485
503
{
486
504
zval * object = ZEND_THIS ;
@@ -502,9 +520,10 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla
502
520
}
503
521
504
522
if (instanceof_function (Z_OBJCE_P (iterator ), zend_ce_aggregate )) {
505
- zend_function * * getiterator_cache = Z_OBJCE_P (iterator )-> iterator_funcs_ptr
506
- ? & Z_OBJCE_P (iterator )-> iterator_funcs_ptr -> zf_new_iterator : NULL ;
507
- zend_call_method_with_0_params (Z_OBJ_P (iterator ), Z_OBJCE_P (iterator ), getiterator_cache , "getiterator" , & aggregate_retval );
523
+ if (spl_get_iterator_from_aggregate (
524
+ & aggregate_retval , Z_OBJCE_P (iterator ), Z_OBJ_P (iterator )) == FAILURE ) {
525
+ RETURN_THROWS ();
526
+ }
508
527
iterator = & aggregate_retval ;
509
528
} else {
510
529
Z_ADDREF_P (iterator );
@@ -526,9 +545,10 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla
526
545
}
527
546
528
547
if (instanceof_function (Z_OBJCE_P (iterator ), zend_ce_aggregate )) {
529
- zend_function * * getiterator_cache = Z_OBJCE_P (iterator )-> iterator_funcs_ptr
530
- ? & Z_OBJCE_P (iterator )-> iterator_funcs_ptr -> zf_new_iterator : NULL ;
531
- zend_call_method_with_0_params (Z_OBJ_P (iterator ), Z_OBJCE_P (iterator ), getiterator_cache , "getiterator" , & aggregate_retval );
548
+ if (spl_get_iterator_from_aggregate (
549
+ & aggregate_retval , Z_OBJCE_P (iterator ), Z_OBJ_P (iterator )) == FAILURE ) {
550
+ RETURN_THROWS ();
551
+ }
532
552
iterator = & aggregate_retval ;
533
553
} else {
534
554
Z_ADDREF_P (iterator );
@@ -1332,15 +1352,7 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
1332
1352
ce = ce_cast ;
1333
1353
}
1334
1354
if (instanceof_function (ce , zend_ce_aggregate )) {
1335
- zend_function * * getiterator_cache =
1336
- ce -> iterator_funcs_ptr ? & ce -> iterator_funcs_ptr -> zf_new_iterator : NULL ;
1337
- zend_call_method_with_0_params (Z_OBJ_P (zobject ), ce , getiterator_cache , "getiterator" , & retval );
1338
- if (EG (exception )) {
1339
- zval_ptr_dtor (& retval );
1340
- return NULL ;
1341
- }
1342
- if (Z_TYPE (retval ) != IS_OBJECT || !instanceof_function (Z_OBJCE (retval ), zend_ce_traversable )) {
1343
- zend_throw_exception_ex (spl_ce_LogicException , 0 , "%s::getIterator() must return an object that implements Traversable" , ZSTR_VAL (ce -> name ));
1355
+ if (spl_get_iterator_from_aggregate (& retval , ce , Z_OBJ_P (zobject )) == FAILURE ) {
1344
1356
return NULL ;
1345
1357
}
1346
1358
zobject = & retval ;
0 commit comments