diff options
Diffstat (limited to 'ext/standard/array.c')
-rw-r--r-- | ext/standard/array.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c index 62279287b6..def7d7c465 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1771,7 +1771,7 @@ PHPAPI int php_prefix_varname(zval *result, zval *prefix, char *var_name, size_t Imports variables into symbol table from an array */ PHP_FUNCTION(extract) { - zval *var_array, *prefix = NULL; + zval *var_array_param, *prefix = NULL; zend_long extract_type = EXTR_OVERWRITE; zval *entry; zend_string *var_name; @@ -1779,14 +1779,15 @@ PHP_FUNCTION(extract) int var_exists, count = 0; int extract_refs = 0; zend_array *symbol_table; + zval var_array; #ifndef FAST_ZPP - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|lz/", &var_array, &extract_type, &prefix) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|lz/", &var_array_param, &extract_type, &prefix) == FAILURE) { return; } #else ZEND_PARSE_PARAMETERS_START(1, 3) - Z_PARAM_ARRAY(var_array) + Z_PARAM_ARRAY(var_array_param) Z_PARAM_OPTIONAL Z_PARAM_LONG(extract_type) Z_PARAM_ZVAL_EX(prefix, 0, 1) @@ -1795,7 +1796,7 @@ PHP_FUNCTION(extract) extract_refs = (extract_type & EXTR_REFS); if (extract_refs) { - SEPARATE_ZVAL(var_array); + SEPARATE_ZVAL(var_array_param); } extract_type &= 0xff; @@ -1825,7 +1826,11 @@ PHP_FUNCTION(extract) } #endif - ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(var_array), num_key, var_name, entry) { + /* The array might be stored in a local variable that will be overwritten. To avoid losing the + * reference in that case we work on a copy. */ + ZVAL_COPY(&var_array, var_array_param); + + ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(var_array), num_key, var_name, entry) { zval final_name; ZVAL_NULL(&final_name); @@ -1926,6 +1931,7 @@ PHP_FUNCTION(extract) } zval_dtor(&final_name); } ZEND_HASH_FOREACH_END(); + zval_ptr_dtor(&var_array); RETURN_LONG(count); } @@ -1938,6 +1944,7 @@ static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_valu ZVAL_DEREF(entry); if (Z_TYPE_P(entry) == IS_STRING) { if ((value_ptr = zend_hash_find_ind(eg_active_symbol_table, Z_STR_P(entry))) != NULL) { + ZVAL_DEREF(value_ptr); ZVAL_COPY(&data, value_ptr); zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data); } @@ -3491,6 +3498,10 @@ static inline zval *array_column_fetch_prop(zval *data, zval *name, zval *rv) } } + if (prop) { + ZVAL_DEREF(prop); + } + return prop; } |