]> granicus.if.org Git - php/commitdiff
Fix extract() overwriting its own argument
authorNikita Popov <nikic@php.net>
Sat, 13 Feb 2016 16:39:26 +0000 (17:39 +0100)
committerNikita Popov <nikic@php.net>
Sat, 13 Feb 2016 16:39:26 +0000 (17:39 +0100)
Already covered by bug46873.phpt under valgrind.

ext/standard/array.c

index 62279287b60e0ebd2f492dc1ee1833198a853d03..336af6ddc0be0c71a8908dedb44f498c6c6be17e 100644 (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);
 }