|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77615 Undefined class constant 'self::DOES_EXIST'
Submitted: 2019-02-13 19:44 UTC Modified: 2019-02-18 10:51 UTC
From: mberchtold at gmail dot com Assigned: dmitry (profile)
Status: Closed Package: opcache
PHP Version: 7.4 OS: Windows 10 x64
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
Block user comment
Status: Assign to:
Bug Type:
From: mberchtold at gmail dot com
New email:
PHP Version: OS:


 [2019-02-13 19:44 UTC] mberchtold at gmail dot com
I'm testing PHP 7.4 ( with preloading on Windows 10. The following exception is thrown and PHP crashes.
Undefined class constant 'self::DOES_EXIST'

in zend_constants.c
				if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
					zend_throw_error(NULL, "Undefined class constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
					goto failure;

The only reference to DOES_EXIST can be found in this file:

Stack trace:
 	php7.dll!zend_exception_error(_zend_object * ex, int severity) Line 969	C
 	php7.dll!zend_error_va_list(int type, const char * format, char * args) Line 1283	C
 	php7.dll!zend_error(int type, const char * format, ...) Line 1478	C
 	php7.dll!zend_throw_error(_zend_class_entry * exception_ce, const char * format, ...) Line 1516	C
>	php7.dll!zend_get_constant_ex(_zend_string * cname, _zend_class_entry * scope, unsigned int flags) Line 376	C
 	php7.dll!zend_ast_evaluate(_zval_struct * result, _zend_ast * ast, _zend_class_entry * scope) Line 505	C
 	php7.dll!zend_ast_evaluate(_zval_struct * result, _zend_ast * ast, _zend_class_entry * scope) Line 646	C
 	php7.dll!zval_update_constant_ex(_zval_struct * p, _zend_class_entry * scope) Line 614	C
 	php_opcache.dll!preload_link() Line 3379	C
 	php_opcache.dll!accel_preload(const char * config) Line 3809	C
 	[Inline Frame] php_opcache.dll!accel_finish_startup() Line 3992	C
 	php_opcache.dll!accel_post_startup() Line 2927	C
 	php7.dll!zend_post_startup() Line 991	C
 	php7.dll!php_module_startup(_sapi_module_struct * sf, _zend_module_entry * additional_modules, unsigned int num_additional_modules) Line 2358	C
 	php.exe!php_cli_startup(_sapi_module_struct * sapi_module) Line 415	C
 	php.exe!main(int argc, char * * argv) Line 1351	C
 	[Inline Frame] php.exe!invoke_main() Line 78	C++
 	php.exe!__scrt_common_main_seh() Line 288	C++
 	kernel32.dll!BaseThreadInitThunk()	Unknown
 	ntdll.dll!RtlUserThreadStart()	Unknown

Test script:
preload zend framework 3 with PHP 7.4 on Windows. Maybe it is enough to preload this file alone:

Expected result:
No crash.

Actual result:
Access violation.


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2019-02-13 19:54 UTC] mberchtold at gmail dot com
To reproduce it, it is sufficient to preload the zend-validator\src folder from ZF3:
 [2019-02-13 19:56 UTC] mberchtold at gmail dot com
This is the preload.php script I'm using:

function _preload($preload, string $pattern = "/\.php$/", array $ignore = []) {
  if (is_array($preload)) {
    foreach ($preload as $path) {
      _preload($path, $pattern, $ignore);
  } else if (is_string($preload)) {
    $path = $preload;
    if (!in_array($path, $ignore)) {
      if (is_dir($path)) {
        if ($dh = opendir($path)) {
          while (($file = readdir($dh)) !== false) {
            if ($file !== "." && $file !== "..") {
              _preload($path . DIRECTORY_SEPARATOR . $file, $pattern, $ignore);
      } else if (is_file($path) && preg_match($pattern, $path)) {
      	// HACK: skip classes with possible reserved names
      	// PHP Fatal error:  Cannot use 'Float' as class name as it is reserved in \vendor\zendframework\zend-db\src\Sql\Ddl\Column\Float.php on line 22
      	$basename = basename($path);
      	if ($basename != 'Float.php'
      		&& $basename != 'Int.php'
      		&& $basename != 'Null.php'
      		&& $basename != 'Object.php'
        	if (!opcache_compile_file($path)) {
	          trigger_error("Preloading Failed", E_USER_ERROR);
 [2019-02-13 21:31 UTC]
-Package: Compile Failure +Package: opcache -PHP Version: Next Minor Version +PHP Version: 7.4
 [2019-02-14 14:45 UTC]
"Typed properties" conflict with "preloading" (even if they are not used).
 [2019-02-14 14:54 UTC]
-Assigned To: +Assigned To: nikic
 [2019-02-14 14:54 UTC]
This is not a Widows related problem.
The problem introduces by "typed properties" that allocate "ce->properties_info_table" at ARENA.


Then assert traps, because we can't keep direct pointer from shared to process memory.

Nikita, can you please take a look.
 [2019-02-15 09:56 UTC]
-Assigned To: nikic +Assigned To: dmitry
 [2019-02-15 09:56 UTC]
@dmitry: I believe the properties_info_table issue should be fixed with

However, this doesn't resolve the original issue. Something like

class Foo {
    const A = self::DOES_NOT_EXIST;

is enough to reproduce a crash. When we call zend_update_constant_ex it may throw an Error, but this of course doesn't work during preloading.
 [2019-02-15 13:50 UTC]
I've fixed the exception issue in

However, there is still some issue for the following case (run under valgrind):

trait T {
    public function test() {
        return 123;

class A {
    const C = UNDEF;
    use T;

I believe the problem is that T::test() is shared with A, but one of the classes is preloaded while the other isn't. Depending on where we encounter it first, we might treat it as immutable or not. But not sure what exactly is happening here.
 [2019-02-18 10:51 UTC]
-Status: Assigned +Status: Closed
 [2019-02-18 10:51 UTC]
The last issue should be fixed by

Please, reopen the bug report, in case of related problems.
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Apr 23 08:01:30 2024 UTC