summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-11-04 15:33:11 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-11-04 15:42:52 +0100
commit670fe594b9cb838ddc78b7da0dc8aa55f3eebf3f (patch)
tree84c24e70f5e50c7ee3c24ad4f5d64096639aa1bd
parentb8f2531ff0ac6a5e7828debd56e8e37ee04a4d6a (diff)
downloadphp-git-670fe594b9cb838ddc78b7da0dc8aa55f3eebf3f.tar.gz
Fix static variable in methods inheritance during preloading
This is now "bug compatible" with the normal behavior, and more imporantly, does not crash :)
-rw-r--r--Zend/zend_inheritance.c16
-rw-r--r--ext/opcache/tests/preload_method_static_vars.inc15
-rw-r--r--ext/opcache/tests/preload_method_static_vars.phpt25
3 files changed, 49 insertions, 7 deletions
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c
index b0f4055be1..7401456d8f 100644
--- a/Zend/zend_inheritance.c
+++ b/Zend/zend_inheritance.c
@@ -90,13 +90,6 @@ static zend_function *zend_duplicate_user_function(zend_function *func) /* {{{ *
new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
memcpy(new_function, func, sizeof(zend_op_array));
- if (ZEND_MAP_PTR_GET(func->op_array.static_variables_ptr)) {
- /* See: Zend/tests/method_static_var.phpt */
- new_function->op_array.static_variables = ZEND_MAP_PTR_GET(func->op_array.static_variables_ptr);
- }
- if (!(GC_FLAGS(new_function->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
- GC_ADDREF(new_function->op_array.static_variables);
- }
if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
ZEND_ASSERT(new_function->op_array.fn_flags & ZEND_ACC_PRELOADED);
@@ -105,6 +98,15 @@ static zend_function *zend_duplicate_user_function(zend_function *func) /* {{{ *
ZEND_MAP_PTR_INIT(new_function->op_array.static_variables_ptr, &new_function->op_array.static_variables);
}
+ HashTable *static_properties_ptr = ZEND_MAP_PTR_GET(func->op_array.static_variables_ptr);
+ if (static_properties_ptr) {
+ /* See: Zend/tests/method_static_var.phpt */
+ ZEND_MAP_PTR_SET(new_function->op_array.static_variables_ptr, static_properties_ptr);
+ GC_TRY_ADDREF(static_properties_ptr);
+ } else {
+ GC_TRY_ADDREF(new_function->op_array.static_variables);
+ }
+
return new_function;
}
/* }}} */
diff --git a/ext/opcache/tests/preload_method_static_vars.inc b/ext/opcache/tests/preload_method_static_vars.inc
new file mode 100644
index 0000000000..03d3c6cb6f
--- /dev/null
+++ b/ext/opcache/tests/preload_method_static_vars.inc
@@ -0,0 +1,15 @@
+<?php
+class Foo {
+ public static function test() {
+ static $i = 0;
+ var_dump(++$i);
+ }
+}
+
+
+Foo::test();
+eval("class Bar extends Foo {}"); // Avoid early binding.
+Foo::test();
+Bar::test();
+Bar::test();
+echo "\n";
diff --git a/ext/opcache/tests/preload_method_static_vars.phpt b/ext/opcache/tests/preload_method_static_vars.phpt
new file mode 100644
index 0000000000..f3d211793c
--- /dev/null
+++ b/ext/opcache/tests/preload_method_static_vars.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Preloading inherited method with separated static vars
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+opcache.preload={PWD}/preload_method_static_vars.inc
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
+?>
+--FILE--
+<?php
+Foo::test();
+Bar::test();
+?>
+--EXPECT--
+int(1)
+int(2)
+int(2)
+int(3)
+
+int(1)
+int(1)