From 9c2fd55d015b792c609e43a334809a2239267b6d Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 20 Jan 2020 12:24:49 +0800 Subject: [PATCH] Fixed bug #79114 (Eval class during preload causes class to be only half available) --- NEWS | 4 ++++ ext/opcache/ZendAccelerator.c | 26 +++++++++++++++++++++-- ext/opcache/tests/preload.inc | 8 +++++++ ext/opcache/tests/preload_bug79114.phpt | 28 +++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 ext/opcache/tests/preload_bug79114.phpt diff --git a/NEWS b/NEWS index 1d708ab487..d8370a2207 100644 --- a/NEWS +++ b/NEWS @@ -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) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index e19980ab05..f7de047506 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -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; } diff --git a/ext/opcache/tests/preload.inc b/ext/opcache/tests/preload.inc index 21ab02298d..10de9390d0 100644 --- a/ext/opcache/tests/preload.inc +++ b/ext/opcache/tests/preload.inc @@ -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() {} "); +} diff --git a/ext/opcache/tests/preload_bug79114.phpt b/ext/opcache/tests/preload_bug79114.phpt new file mode 100644 index 0000000000..345a6bd83a --- /dev/null +++ b/ext/opcache/tests/preload_bug79114.phpt @@ -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-- + +--FILE-- + +--EXPECTF-- +bool(true) +bool(true) +array(1) { + ["Foo"]=> + string(3) "Foo" +} -- 2.49.0