diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 824c6ccb3e1..0b60d50a1a2 100755 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -2177,10 +2177,14 @@ static int pdo_stmt_iter_valid(zend_object_iterator *iter TSRMLS_DC) return I->fetch_ahead ? SUCCESS : FAILURE; } -static void pdo_stmt_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) +static void pdo_stmt_iter_get_data(zend_object_iterator *iter, zval ***data, int by_ref TSRMLS_DC) { struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter->data; + if (by_ref) { + zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); + } + /* sanity */ if (!I->fetch_ahead) { *data = NULL; @@ -2237,11 +2241,15 @@ static zend_object_iterator_funcs pdo_stmt_iter_funcs = { NULL }; -zend_object_iterator *pdo_stmt_iter_get(zend_class_entry *ce, zval *object TSRMLS_DC) +zend_object_iterator *pdo_stmt_iter_get(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) { pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(object TSRMLS_CC); struct php_pdo_iterator *I; + if (by_ref) { + zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); + } + I = ecalloc(1, sizeof(*I)); I->iter.funcs = &pdo_stmt_iter_funcs; I->iter.data = I; diff --git a/ext/pdo/php_pdo_int.h b/ext/pdo/php_pdo_int.h index a2f49a6ef60..6ed411cb592 100755 --- a/ext/pdo/php_pdo_int.h +++ b/ext/pdo/php_pdo_int.h @@ -42,7 +42,7 @@ extern zend_object_value pdo_dbstmt_new(zend_class_entry *ce TSRMLS_DC); extern zend_function_entry pdo_dbstmt_functions[]; extern zend_class_entry *pdo_dbstmt_ce; void pdo_dbstmt_free_storage(pdo_stmt_t *stmt TSRMLS_DC); -zend_object_iterator *pdo_stmt_iter_get(zend_class_entry *ce, zval *object TSRMLS_DC); +zend_object_iterator *pdo_stmt_iter_get(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC); extern zend_object_handlers pdo_dbstmt_object_handlers; int pdo_stmt_describe_columns(pdo_stmt_t *stmt TSRMLS_DC); int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, int skip_first_arg); diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index b5552108a15..1b2455673e5 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -1769,9 +1769,14 @@ static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data TSRML return NULL; } -zend_object_iterator *php_sxe_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC) +zend_object_iterator *php_sxe_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) { - php_sxe_iterator *iterator = emalloc(sizeof(php_sxe_iterator)); + php_sxe_iterator *iterator; + + if (by_ref) { + zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); + } + iterator = emalloc(sizeof(php_sxe_iterator)); object->refcount++; iterator->intern.data = (void*)object; diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index a715c66a8c9..7b759fd2b52 100755 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -757,10 +757,27 @@ zend_object_iterator_funcs spl_array_it_funcs = { spl_array_it_rewind }; -zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC) /* {{{ */ +zend_object_iterator *spl_array_obj_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */ { - spl_array_it *iterator = emalloc(sizeof(spl_array_it)); - spl_array_object *array_object = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + /* disable by_ref check */ + /* We enable by ref if the returned thing does. If it is an ArrayIterator */ + /* or derived then it does if it's current() method is not overloaded. */ + return zend_user_it_get_new_iterator(ce, object, 0 TSRMLS_CC); +} +/* }}} */ + +zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */ +{ + spl_array_it *iterator; + spl_array_object *array_object; + +#if MBO_0 + if (by_ref && /* check current() is overloaded, else it works */) { + zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); + } +#endif + iterator = emalloc(sizeof(spl_array_it)); + array_object = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); object->refcount++; iterator->intern.data = (void*)object; @@ -1392,6 +1409,8 @@ PHP_MINIT_FUNCTION(spl_array) REGISTER_SPL_IMPLEMENTS(ArrayObject, Aggregate); REGISTER_SPL_IMPLEMENTS(ArrayObject, ArrayAccess); memcpy(&spl_handler_ArrayObject, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + spl_ce_ArrayObject->get_iterator = spl_array_obj_get_iterator; + spl_handler_ArrayObject.clone_obj = spl_array_object_clone; spl_handler_ArrayObject.read_dimension = spl_array_read_dimension; spl_handler_ArrayObject.write_dimension = spl_array_write_dimension; diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 26ad85c365b..6fde9737ccd 100755 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -963,10 +963,16 @@ zend_object_iterator_funcs spl_filesystem_dir_it_funcs = { }; /* {{{ spl_ce_dir_get_iterator */ -zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC) +zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) { - spl_filesystem_dir_it *iterator = emalloc(sizeof(spl_filesystem_dir_it)); - spl_filesystem_object *dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_filesystem_dir_it *iterator; + spl_filesystem_object *dir_object; + + if (by_ref) { + zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); + } + iterator = emalloc(sizeof(spl_filesystem_dir_it)); + dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC); object->refcount += 2;; iterator->intern.data = (void*)object; @@ -1168,10 +1174,16 @@ zend_object_iterator_funcs spl_filesystem_tree_it_funcs = { }; /* {{{ spl_ce_dir_get_iterator */ -zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC) +zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) { - spl_filesystem_dir_it *iterator = emalloc(sizeof(spl_filesystem_dir_it)); - spl_filesystem_object *dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_filesystem_dir_it *iterator; + spl_filesystem_object *dir_object; + + if (by_ref) { + zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); + } + iterator = emalloc(sizeof(spl_filesystem_dir_it)); + dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC); object->refcount++; iterator->intern.data = (void*)object; diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index b42c69c8b90..642a1a276d8 100755 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -278,7 +278,7 @@ next_step: object->iterators[object->level].state = RS_NEXT; } object->iterators = erealloc(object->iterators, sizeof(spl_sub_iterator) * (++object->level+1)); - sub_iter = ce->get_iterator(ce, child TSRMLS_CC); + sub_iter = ce->get_iterator(ce, child, 0 TSRMLS_CC); object->iterators[object->level].iterator = sub_iter; object->iterators[object->level].zobject = child; object->iterators[object->level].ce = ce; @@ -340,10 +340,16 @@ static void spl_recursive_it_rewind(zend_object_iterator *iter TSRMLS_DC) spl_recursive_it_rewind_ex((spl_recursive_it_object*)iter->data, ((spl_recursive_it_iterator*)iter)->zobject TSRMLS_CC); } -static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce, zval *zobject TSRMLS_DC) +static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce, zval *zobject, int by_ref TSRMLS_DC) { - spl_recursive_it_iterator *iterator = emalloc(sizeof(spl_recursive_it_iterator)); - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(zobject TSRMLS_CC); + spl_recursive_it_iterator *iterator; + spl_recursive_it_object *object; + + if (by_ref) { + zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); + } + iterator = emalloc(sizeof(spl_recursive_it_iterator)); + object = (spl_recursive_it_object*)zend_object_store_get_object(zobject TSRMLS_CC); zobject->refcount++; iterator->intern.data = (void*)object; @@ -430,7 +436,7 @@ SPL_METHOD(RecursiveIteratorIterator, __construct) intern->nextElement = NULL; } ce_iterator = Z_OBJCE_P(iterator); /* respect inheritance, don't use spl_ce_RecursiveIterator */ - intern->iterators[0].iterator = ce_iterator->get_iterator(ce_iterator, iterator TSRMLS_CC); + intern->iterators[0].iterator = ce_iterator->get_iterator(ce_iterator, iterator, 0 TSRMLS_CC); if (inc_refcount) { iterator->refcount++; } @@ -918,7 +924,7 @@ static inline spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAME case DIT_AppendIterator: spl_instantiate(U_CLASS_ENTRY(spl_ce_ArrayIterator), &intern->u.append.zarrayit, 1 TSRMLS_CC); zend_call_method_with_0_params(&intern->u.append.zarrayit, U_CLASS_ENTRY(spl_ce_ArrayIterator), &U_CLASS_ENTRY(spl_ce_ArrayIterator)->constructor, "__construct", NULL); - intern->u.append.iterator = U_CLASS_ENTRY(spl_ce_ArrayIterator)->get_iterator(U_CLASS_ENTRY(spl_ce_ArrayIterator), intern->u.append.zarrayit TSRMLS_CC); + intern->u.append.iterator = U_CLASS_ENTRY(spl_ce_ArrayIterator)->get_iterator(U_CLASS_ENTRY(spl_ce_ArrayIterator), intern->u.append.zarrayit, 0 TSRMLS_CC); php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); return intern; #if HAVE_PCRE || HAVE_BUNDLED_PCRE @@ -954,7 +960,7 @@ static inline spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAME intern->inner.zobject = zobject; intern->inner.ce = dit_type == DIT_IteratorIterator ? ce : Z_OBJCE_P(zobject); intern->inner.object = zend_object_store_get_object(zobject TSRMLS_CC); - intern->inner.iterator = intern->inner.ce->get_iterator(intern->inner.ce, zobject TSRMLS_CC); + intern->inner.iterator = intern->inner.ce->get_iterator(intern->inner.ce, zobject, 0 TSRMLS_CC); php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); return intern; @@ -2209,7 +2215,7 @@ int spl_append_it_next_iterator(spl_dual_it_object *intern TSRMLS_DC) /* {{{*/ intern->inner.zobject = *it; intern->inner.ce = Z_OBJCE_PP(it); intern->inner.object = zend_object_store_get_object(*it TSRMLS_CC); - intern->inner.iterator = intern->inner.ce->get_iterator(intern->inner.ce, *it TSRMLS_CC); + intern->inner.iterator = intern->inner.ce->get_iterator(intern->inner.ce, *it, 0 TSRMLS_CC); spl_dual_it_rewind(intern TSRMLS_CC); return SUCCESS; } else { @@ -2362,7 +2368,7 @@ PHP_FUNCTION(iterator_to_array) array_init(return_value); - iter = Z_OBJCE_P(obj)->get_iterator(Z_OBJCE_P(obj), obj TSRMLS_CC); + iter = Z_OBJCE_P(obj)->get_iterator(Z_OBJCE_P(obj), obj, 0 TSRMLS_CC); if (iter->funcs->rewind) { iter->funcs->rewind(iter TSRMLS_CC); @@ -2406,7 +2412,7 @@ PHP_FUNCTION(iterator_count) RETURN_FALSE; } - iter = Z_OBJCE_P(obj)->get_iterator(Z_OBJCE_P(obj), obj TSRMLS_CC); + iter = Z_OBJCE_P(obj)->get_iterator(Z_OBJCE_P(obj), obj, 0 TSRMLS_CC); if (iter->funcs->rewind) { iter->funcs->rewind(iter TSRMLS_CC); diff --git a/ext/unicode/unicode_iterators.c b/ext/unicode/unicode_iterators.c index 377ebfd588f..a3de0ae05ac 100644 --- a/ext/unicode/unicode_iterators.c +++ b/ext/unicode/unicode_iterators.c @@ -239,10 +239,16 @@ zend_object_iterator_funcs text_iter_cp_funcs = { text_iter_rewind, }; -static zend_object_iterator* text_iter_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC) +static zend_object_iterator* text_iter_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) { - text_iter_it* iterator = emalloc(sizeof(text_iter_it)); - text_iter_obj* iter_object = (text_iter_obj *) zend_object_store_get_object(object TSRMLS_CC); + text_iter_it* iterator; + text_iter_obj* iter_object; + + if (by_ref) { + zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); + } + iterator = emalloc(sizeof(text_iter_it)); + iter_object = (text_iter_obj *) zend_object_store_get_object(object TSRMLS_CC); ZVAL_ADDREF(object); iterator->intern.data = (void *) object;