]> granicus.if.org Git - php/commitdiff
Fixed bug #79114 (Eval class during preload causes class to be only half available)
authorXinchen Hui <laruence@gmail.com>
Mon, 20 Jan 2020 04:24:49 +0000 (12:24 +0800)
committerXinchen Hui <laruence@gmail.com>
Mon, 20 Jan 2020 04:24:49 +0000 (12:24 +0800)
NEWS
ext/opcache/ZendAccelerator.c
ext/opcache/tests/preload.inc
ext/opcache/tests/preload_bug79114.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 1d708ab487367d4fa0db7639976ef304067354c8..d8370a22076f4bdb1e77589798dcc0fed2494c74 100644 (file)
--- 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)
index e19980ab05bd8452a34d160800d4318677d4665a..f7de04750688f055c7984acd7526fb34d69a5c2d 100644 (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;
                                }
index 21ab02298dfb1dd9153e33a5c786ca2ff00d9704..10de9390d0333701fed07da6772e1f80393c553b 100644 (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() {} ");
+}
diff --git a/ext/opcache/tests/preload_bug79114.phpt b/ext/opcache/tests/preload_bug79114.phpt
new file mode 100644 (file)
index 0000000..345a6bd
--- /dev/null
@@ -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"
+}