Skip to content

Commit

Permalink
Fix static variable in methods inheritance during preloading
Browse files Browse the repository at this point in the history
This is now "bug compatible" with the normal behavior, and more
imporantly, does not crash :)
  • Loading branch information
nikic committed Nov 4, 2020
1 parent b8f2531 commit 670fe59
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 7 deletions.
16 changes: 9 additions & 7 deletions Zend/zend_inheritance.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
/* }}} */
Expand Down
15 changes: 15 additions & 0 deletions ext/opcache/tests/preload_method_static_vars.inc
Original file line number Diff line number Diff line change
@@ -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";
25 changes: 25 additions & 0 deletions ext/opcache/tests/preload_method_static_vars.phpt
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit 670fe59

Please sign in to comment.