Fixed bug #79114 (Eval class during preload causes class to be only half available)

This commit is contained in:
Xinchen Hui 2020-01-20 12:24:49 +08:00
parent 384dfe331b
commit 9c2fd55d01
4 changed files with 64 additions and 2 deletions

4
NEWS
View File

@ -13,6 +13,10 @@ PHP NEWS
. Fixed bug #79084 (mysqlnd may fetch wrong column indexes with MYSQLI_BOTH).
(cmb)
- Opcache:
. Fixed #79114 (Eval class during preload causes class to be only half
available). (Laruence)
- Reflection:
. Fixed bug #79115 (ReflectionClass::isCloneable call reflected class
__destruct). (Nikita)

View File

@ -3211,6 +3211,18 @@ static void preload_restart(void)
}
}
static size_t preload_try_strip_filename(zend_string *filename) {
/*FIXME: better way to hanlde eval()'d code? see COMPILED_STRING_DESCRIPTION_FORMAT */
if (ZSTR_LEN(filename) > sizeof(" eval()'d code")
&& *(ZSTR_VAL(filename) + ZSTR_LEN(filename) - sizeof(" eval()'d code")) == ':') {
const char *cfilename = ZSTR_VAL(filename);
size_t cfilenamelen = ZSTR_LEN(filename) - sizeof(" eval()'d code") - 2 /* :*/;
while (cfilenamelen && cfilename[--cfilenamelen] != '(');
return cfilenamelen;
}
return 0;
}
static void preload_move_user_functions(HashTable *src, HashTable *dst)
{
Bucket *p;
@ -3227,7 +3239,12 @@ static void preload_move_user_functions(HashTable *src, HashTable *dst)
if (function->op_array.filename != filename) {
filename = function->op_array.filename;
if (filename) {
copy = zend_hash_exists(preload_scripts, filename);
if (!(copy = zend_hash_exists(preload_scripts, filename))) {
size_t eval_len = preload_try_strip_filename(filename);
if (eval_len) {
copy = zend_hash_str_exists(preload_scripts, ZSTR_VAL(filename), eval_len);
}
}
} else {
copy = 0;
}
@ -3261,7 +3278,12 @@ static void preload_move_user_classes(HashTable *src, HashTable *dst)
if (ce->info.user.filename != filename) {
filename = ce->info.user.filename;
if (filename) {
copy = zend_hash_exists(preload_scripts, filename);
if (!(copy = zend_hash_exists(preload_scripts, filename))) {
size_t eval_len = preload_try_strip_filename(filename);
if (eval_len) {
copy = zend_hash_str_exists(preload_scripts, ZSTR_VAL(filename), eval_len);
}
}
} else {
copy = 0;
}

View File

@ -48,3 +48,11 @@ class Z2 extends Z {}
function get_anon() {
return new class {};
}
if (!isset($rt)) {
eval("class Foo {}");
class Bar extends Foo {}
eval("function f3() {} ");
}

View File

@ -0,0 +1,28 @@
--TEST--
Bug #79114 (Eval class during preload causes class to be only half available)
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload.inc
--SKIPIF--
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
var_dump(class_exists(Foo::class));
var_dump(class_exists(Bar::class));
new Bar();
var_dump(class_parents('Bar'));
new Foo();
f3();
?>
--EXPECTF--
bool(true)
bool(true)
array(1) {
["Foo"]=>
string(3) "Foo"
}