HashTable *thash;
zend_fcall_info orig_array_walk_fci;
zend_fcall_info_cache orig_array_walk_fci_cache;
- zval rv;
+ zval ref;
+ ZVAL_COPY_VALUE(&ref, zv);
- SEPARATE_ARRAY(Z_REFVAL_P(zv));
- ZVAL_COPY_VALUE(&rv, Z_REFVAL_P(zv));
- thash = Z_ARRVAL(rv);
+ ZVAL_DEREF(zv);
+ SEPARATE_ARRAY(zv);
+ thash = Z_ARRVAL_P(zv);
- if (thash->u.v.nApplyCount > 1) {
+ if (GC_IS_RECURSIVE(thash)) {
php_error_docref(NULL, E_WARNING, "recursion detected");
- if (!was_ref) {
- ZVAL_UNREF(zv);
- }
result = FAILURE;
break;
}
orig_array_walk_fci = BG(array_walk_fci);
orig_array_walk_fci_cache = BG(array_walk_fci_cache);
- Z_ADDREF(rv);
+ Z_ADDREF(ref);
- thash->u.v.nApplyCount++;
+ GC_PROTECT_RECURSION(thash);
- result = php_array_walk(&rv, userdata, recursive);
- if (Z_TYPE_P(Z_REFVAL_P(zv)) == IS_ARRAY && thash == Z_ARRVAL_P(Z_REFVAL_P(zv))) {
+ result = php_array_walk(zv, userdata, recursive);
+ if (Z_TYPE_P(Z_REFVAL(ref)) == IS_ARRAY && thash == Z_ARRVAL_P(Z_REFVAL(ref))) {
/* If the hashtable changed in the meantime, we'll "leak" this apply count
* increment -- our reference to thash is no longer valid. */
- thash->u.v.nApplyCount--;
+ GC_UNPROTECT_RECURSION(thash);
}
- zval_ptr_dtor(&rv);
+ zval_ptr_dtor(&ref);
/* restore the fcall info and cache */
BG(array_walk_fci) = orig_array_walk_fci;