]> granicus.if.org Git - php/commitdiff
Fixed bug #77669
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 28 Feb 2019 08:58:01 +0000 (09:58 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Thu, 28 Feb 2019 08:58:01 +0000 (09:58 +0100)
NEWS
ext/standard/array.c
ext/standard/tests/array/bug77669.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 65eb3a98514ba331035a137d4cfc22d04a73c2dd..c7faa0b9078483284320946a4bcb5b43b7c7eb5e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,8 @@ PHP                                                                        NEWS
 - Standard:
   . Fixed bug #77664 (Segmentation fault when using undefined constant in
     custom wrapper). (Laruence)
+  . Fixed bug #77669 (Crash in extract() when overwriting extracted array).
+    (Nikita)
 
 - MySQLi:
   . Fixed bug #77597 (mysqli_fetch_field hangs scripts). (Nikita)
index e810defcdaf73e4fc9d517bab47ee169007e8122..61f0f98f79c66ab8b9e408d4656117ca4eafa9a4 100644 (file)
@@ -2528,35 +2528,33 @@ PHP_FUNCTION(extract)
                                break;
                }
        } else {
+               /* The array might be stored in a local variable that will be overwritten */
+               zval array_copy;
+               ZVAL_COPY(&array_copy, var_array_param);
                switch (extract_type) {
                        case EXTR_IF_EXISTS:
-                               count = php_extract_if_exists(Z_ARRVAL_P(var_array_param), symbol_table);
+                               count = php_extract_if_exists(Z_ARRVAL(array_copy), symbol_table);
                                break;
                        case EXTR_OVERWRITE:
-                               {
-                                       zval zv;
-                                       /* The array might be stored in a local variable that will be overwritten */
-                                       ZVAL_COPY(&zv, var_array_param);
-                                       count = php_extract_overwrite(Z_ARRVAL(zv), symbol_table);
-                                       zval_ptr_dtor(&zv);
-                               }
+                               count = php_extract_overwrite(Z_ARRVAL(array_copy), symbol_table);
                                break;
                        case EXTR_PREFIX_IF_EXISTS:
-                               count = php_extract_prefix_if_exists(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
+                               count = php_extract_prefix_if_exists(Z_ARRVAL(array_copy), symbol_table, prefix);
                                break;
                        case EXTR_PREFIX_SAME:
-                               count = php_extract_prefix_same(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
+                               count = php_extract_prefix_same(Z_ARRVAL(array_copy), symbol_table, prefix);
                                break;
                        case EXTR_PREFIX_ALL:
-                               count = php_extract_prefix_all(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
+                               count = php_extract_prefix_all(Z_ARRVAL(array_copy), symbol_table, prefix);
                                break;
                        case EXTR_PREFIX_INVALID:
-                               count = php_extract_prefix_invalid(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
+                               count = php_extract_prefix_invalid(Z_ARRVAL(array_copy), symbol_table, prefix);
                                break;
                        default:
-                               count = php_extract_skip(Z_ARRVAL_P(var_array_param), symbol_table);
+                               count = php_extract_skip(Z_ARRVAL(array_copy), symbol_table);
                                break;
                }
+               zval_ptr_dtor(&array_copy);
        }
 
        RETURN_LONG(count);
diff --git a/ext/standard/tests/array/bug77669.phpt b/ext/standard/tests/array/bug77669.phpt
new file mode 100644 (file)
index 0000000..1e34f45
--- /dev/null
@@ -0,0 +1,35 @@
+--TEST--
+Bug #77669: Crash in extract() when overwriting extracted array
+--FILE--
+<?php
+
+function test($mode) {
+    $foo = [];
+    $foo["foo"] = 42;
+    $foo["bar"] = 24;
+    extract($foo, $mode, "");
+    $prefix_foo = [];
+    $prefix_foo["foo"] = 42;
+    $prefix_foo["bar"] = 24;
+    extract($prefix_foo, $mode, "prefix");
+}
+
+test(EXTR_OVERWRITE);
+test(EXTR_SKIP);
+test(EXTR_IF_EXISTS);
+test(EXTR_PREFIX_SAME);
+test(EXTR_PREFIX_ALL);
+test(EXTR_PREFIX_INVALID);
+test(EXTR_PREFIX_IF_EXISTS);
+test(EXTR_REFS | EXTR_OVERWRITE);
+test(EXTR_REFS | EXTR_SKIP);
+test(EXTR_REFS | EXTR_IF_EXISTS);
+test(EXTR_REFS | EXTR_PREFIX_SAME);
+test(EXTR_REFS | EXTR_PREFIX_ALL);
+test(EXTR_REFS | EXTR_PREFIX_INVALID);
+test(EXTR_REFS | EXTR_PREFIX_IF_EXISTS);
+
+?>
+===DONE===
+--EXPECT--
+===DONE===