summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-02-28 09:58:01 +0100
committerNikita Popov <nikita.ppv@gmail.com>2019-02-28 09:58:01 +0100
commit9ad9cc71ff3bb45532b22b4145ea3af90692b364 (patch)
tree13b4096136c11ee3f0ea7c79477c2e7ec06adeb8
parentaf37d58cf7b77814b93ea97a8dcd2afb46c4424e (diff)
downloadphp-git-9ad9cc71ff3bb45532b22b4145ea3af90692b364.tar.gz
Fixed bug #77669
-rw-r--r--NEWS2
-rw-r--r--ext/standard/array.c24
-rw-r--r--ext/standard/tests/array/bug77669.phpt35
3 files changed, 48 insertions, 13 deletions
diff --git a/NEWS b/NEWS
index 65eb3a9851..c7faa0b907 100644
--- 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)
diff --git a/ext/standard/array.c b/ext/standard/array.c
index e810defcda..61f0f98f79 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -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
index 0000000000..1e34f453a2
--- /dev/null
+++ b/ext/standard/tests/array/bug77669.phpt
@@ -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===