]> granicus.if.org Git - php/commitdiff
Fix static variable in methods inheritance during preloading
authorNikita Popov <nikita.ppv@gmail.com>
Wed, 4 Nov 2020 14:33:11 +0000 (15:33 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Wed, 4 Nov 2020 14:42:52 +0000 (15:42 +0100)
This is now "bug compatible" with the normal behavior, and more
imporantly, does not crash :)

Zend/zend_inheritance.c
ext/opcache/tests/preload_method_static_vars.inc [new file with mode: 0644]
ext/opcache/tests/preload_method_static_vars.phpt [new file with mode: 0644]

index b0f4055be1bfe43f893369fc83e60d4d11368a16..7401456d8f09b6e4befc97583754ed7eae453f1e 100644 (file)
@@ -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 (file)
index 0000000..03d3c6c
--- /dev/null
@@ -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 (file)
index 0000000..f3d2117
--- /dev/null
@@ -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)