Fix extract() overwriting its own argument

Already covered by bug46873.phpt under valgrind.
This commit is contained in:
Nikita Popov 2016-02-13 17:39:26 +01:00
parent 70c8db08c6
commit 7f474086e3

View File

@ -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,6 +1779,7 @@ 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) {
@ -1786,7 +1787,7 @@ PHP_FUNCTION(extract)
}
#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);
}