From d708d3c596aa16afa9ca4906ea1fa6579b74b494 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 11 Mar 2014 22:33:28 +0400 Subject: [PATCH] Fixed passing arguments by reference from internal functions --- Zend/zend_API.c | 7 ++++++- Zend/zend_execute_API.c | 7 ++++++- ext/standard/array.c | 39 +++++++++++++++++++++++++++++---------- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index c0f7d533b1..a9c10b6c32 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3344,6 +3344,11 @@ ZEND_API int zend_fcall_info_init(zval *callable, uint check_flags, zend_fcall_i ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /* {{{ */ { if (fci->params) { + int i; + + for (i = 0; i < fci->param_count; i++) { + zval_ptr_dtor(&fci->params[i]); + } if (free_mem) { efree(fci->params); fci->params = NULL; @@ -3390,7 +3395,7 @@ ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) /* zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos); while ((arg = zend_hash_get_current_data_ex(Z_ARRVAL_P(args), &pos)) != NULL) { - ZVAL_COPY_VALUE(params, arg); + ZVAL_COPY(params, arg); params++; zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos); } diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 8faba97fc7..ea02c0f160 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -856,7 +856,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS return FAILURE; } - zval_copy_ctor(&fci->params[i]); + if (Z_REFCOUNTED(fci->params[i])) { + Z_DELREF(fci->params[i]); + } + ZVAL_DUP(&tmp, &fci->params[i]); + ZVAL_NEW_REF(&fci->params[i], &tmp); + Z_ADDREF(fci->params[i]); } else if (!Z_ISREF(fci->params[i])) { if (Z_REFCOUNTED(fci->params[i])) { Z_ADDREF(fci->params[i]); diff --git a/ext/standard/array.c b/ext/standard/array.c index 760413a03d..fb594fbbbe 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -587,8 +587,8 @@ static int php_array_user_compare(const void *a, const void *b TSRMLS_DC) /* {{{ f = (Bucket *) a; s = (Bucket *) b; - ZVAL_COPY_VALUE(&args[0], &f->val); - ZVAL_COPY_VALUE(&args[1], &s->val); + ZVAL_COPY(&args[0], &f->val); + ZVAL_COPY(&args[1], &s->val); BG(user_compare_fci).param_count = 2; BG(user_compare_fci).params = args; @@ -600,8 +600,12 @@ static int php_array_user_compare(const void *a, const void *b TSRMLS_DC) /* {{{ convert_to_long_ex(&retval); ret = Z_LVAL(retval); zval_ptr_dtor(&retval); + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&args[0]); return ret < 0 ? -1 : ret > 0 ? 1 : 0; } else { + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&args[0]); return 0; } } @@ -1049,7 +1053,7 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive /* Iterate through hash */ zend_hash_internal_pointer_reset(target_hash); while (!EG(exception) && (zv = zend_hash_get_current_data(target_hash)) != NULL) { - ZVAL_COPY_VALUE(&args[0], zv); + ZVAL_COPY(&args[0], zv); if (recursive && Z_TYPE(args[0]) == IS_ARRAY) { HashTable *thash; zend_fcall_info orig_array_walk_fci; @@ -1059,8 +1063,9 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive thash = Z_ARRVAL(args[0]); if (thash->nApplyCount > 1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected"); + zval_ptr_dtor(&args[0]); if (userdata) { - zval_ptr_dtor(userdata); + zval_ptr_dtor(&args[2]); } return 0; } @@ -1084,6 +1089,7 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive if (zend_call_function(&BG(array_walk_fci), &BG(array_walk_fci_cache) TSRMLS_CC) == SUCCESS) { zval_ptr_dtor(&retval); } else { + zval_ptr_dtor(&args[0]); if (Z_TYPE(args[1]) != IS_UNDEF) { zval_ptr_dtor(&args[1]); ZVAL_UNDEF(&args[1]); @@ -1092,6 +1098,7 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive } } + zval_ptr_dtor(&args[0]); if (Z_TYPE(args[1]) != IS_UNDEF) { zval_ptr_dtor(&args[1]); ZVAL_UNDEF(&args[1]); @@ -1100,7 +1107,7 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive } if (userdata) { - zval_ptr_dtor(userdata); + zval_ptr_dtor(&args[2]); } return 0; } @@ -4253,18 +4260,19 @@ PHP_FUNCTION(array_filter) } } if (use_type != ARRAY_FILTER_USE_KEY) { - ZVAL_COPY_VALUE(&args[0], operand); + ZVAL_COPY(&args[0], operand); } fci.params = args; if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS) { + zval_ptr_dtor(&args[0]); + if (use_type == ARRAY_FILTER_USE_BOTH) { + zval_ptr_dtor(&args[1]); + } if (!ZVAL_IS_UNDEF(&retval)) { int retval_true = zend_is_true(&retval TSRMLS_CC); zval_ptr_dtor(&retval); - if (use_type) { - zval_ptr_dtor(&args[0]); - } if (!retval_true) { continue; } @@ -4272,6 +4280,10 @@ PHP_FUNCTION(array_filter) continue; } } else { + zval_ptr_dtor(&args[0]); + if (use_type == ARRAY_FILTER_USE_BOTH) { + zval_ptr_dtor(&args[1]); + } php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the filter callback"); return; } @@ -4366,7 +4378,7 @@ PHP_FUNCTION(array_map) if (k < array_len[i]) { zval *zv = zend_hash_get_current_data_ex(Z_ARRVAL_P(args[i]), &array_pos[i]); - ZVAL_COPY_VALUE(¶ms[i], zv); + ZVAL_COPY(¶ms[i], zv); /* It is safe to store only last value of key type, because * this loop will run just once if there is only 1 array. */ @@ -4396,8 +4408,15 @@ PHP_FUNCTION(array_map) efree(args); efree(array_pos); zval_dtor(return_value); + for (i = 0; i < n_arrays; i++) { + zval_ptr_dtor(¶ms[i]); + } efree(params); RETURN_NULL(); + } else { + for (i = 0; i < n_arrays; i++) { + zval_ptr_dtor(¶ms[i]); + } } } -- 2.40.0