Skip to content

Commit 9c2fd55

Browse files
committed
Fixed bug #79114 (Eval class during preload causes class to be only half available)
1 parent 384dfe3 commit 9c2fd55

File tree

4 files changed

+64
-2
lines changed

4 files changed

+64
-2
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ PHP NEWS
1313
. Fixed bug #79084 (mysqlnd may fetch wrong column indexes with MYSQLI_BOTH).
1414
(cmb)
1515

16+
- Opcache:
17+
. Fixed #79114 (Eval class during preload causes class to be only half
18+
available). (Laruence)
19+
1620
- Reflection:
1721
. Fixed bug #79115 (ReflectionClass::isCloneable call reflected class
1822
__destruct). (Nikita)

ext/opcache/ZendAccelerator.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3211,6 +3211,18 @@ static void preload_restart(void)
32113211
}
32123212
}
32133213

3214+
static size_t preload_try_strip_filename(zend_string *filename) {
3215+
/*FIXME: better way to hanlde eval()'d code? see COMPILED_STRING_DESCRIPTION_FORMAT */
3216+
if (ZSTR_LEN(filename) > sizeof(" eval()'d code")
3217+
&& *(ZSTR_VAL(filename) + ZSTR_LEN(filename) - sizeof(" eval()'d code")) == ':') {
3218+
const char *cfilename = ZSTR_VAL(filename);
3219+
size_t cfilenamelen = ZSTR_LEN(filename) - sizeof(" eval()'d code") - 2 /* :*/;
3220+
while (cfilenamelen && cfilename[--cfilenamelen] != '(');
3221+
return cfilenamelen;
3222+
}
3223+
return 0;
3224+
}
3225+
32143226
static void preload_move_user_functions(HashTable *src, HashTable *dst)
32153227
{
32163228
Bucket *p;
@@ -3227,7 +3239,12 @@ static void preload_move_user_functions(HashTable *src, HashTable *dst)
32273239
if (function->op_array.filename != filename) {
32283240
filename = function->op_array.filename;
32293241
if (filename) {
3230-
copy = zend_hash_exists(preload_scripts, filename);
3242+
if (!(copy = zend_hash_exists(preload_scripts, filename))) {
3243+
size_t eval_len = preload_try_strip_filename(filename);
3244+
if (eval_len) {
3245+
copy = zend_hash_str_exists(preload_scripts, ZSTR_VAL(filename), eval_len);
3246+
}
3247+
}
32313248
} else {
32323249
copy = 0;
32333250
}
@@ -3261,7 +3278,12 @@ static void preload_move_user_classes(HashTable *src, HashTable *dst)
32613278
if (ce->info.user.filename != filename) {
32623279
filename = ce->info.user.filename;
32633280
if (filename) {
3264-
copy = zend_hash_exists(preload_scripts, filename);
3281+
if (!(copy = zend_hash_exists(preload_scripts, filename))) {
3282+
size_t eval_len = preload_try_strip_filename(filename);
3283+
if (eval_len) {
3284+
copy = zend_hash_str_exists(preload_scripts, ZSTR_VAL(filename), eval_len);
3285+
}
3286+
}
32653287
} else {
32663288
copy = 0;
32673289
}

ext/opcache/tests/preload.inc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,11 @@ class Z2 extends Z {}
4848
function get_anon() {
4949
return new class {};
5050
}
51+
52+
if (!isset($rt)) {
53+
eval("class Foo {}");
54+
55+
class Bar extends Foo {}
56+
57+
eval("function f3() {} ");
58+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
Bug #79114 (Eval class during preload causes class to be only half available)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
opcache.preload={PWD}/preload.inc
8+
--SKIPIF--
9+
<?php
10+
require_once('skipif.inc');
11+
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
12+
?>
13+
--FILE--
14+
<?php
15+
var_dump(class_exists(Foo::class));
16+
var_dump(class_exists(Bar::class));
17+
new Bar();
18+
var_dump(class_parents('Bar'));
19+
new Foo();
20+
f3();
21+
?>
22+
--EXPECTF--
23+
bool(true)
24+
bool(true)
25+
array(1) {
26+
["Foo"]=>
27+
string(3) "Foo"
28+
}

0 commit comments

Comments
 (0)