Bug #77615 [Asn]: Undefined class constant 'self::DOES_EXIST'

From: Date: Fri, 15 Feb 2019 09:56:36 +0000
Subject: Bug #77615 [Asn]: Undefined class constant 'self::DOES_EXIST'
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-219589@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=77615&edit=1

 ID:                 77615
 Updated by:         nikic@php.net
 Reported by:        mberchtold at gmail dot com
 Summary:            Undefined class constant 'self::DOES_EXIST'
 Status:             Assigned
 Type:               Bug
 Package:            opcache
 Operating System:   Windows 10 x64
 PHP Version:        7.4
-Assigned To:        nikic
+Assigned To:        dmitry
 Block user comment: N
 Private report:     N

 New Comment:

@dmitry: I believe the properties_info_table issue should be fixed with https://github.com/php/php-src/commit/ffc7e953ea908f05703d573faadc51707936321c.

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.


Previous Comments:
------------------------------------------------------------------------
[2019-02-14 14:54:24] dmitry@php.net

This is not a Widows related problem.
The problem introduces by "typed properties" that allocate
"ce->properties_info_table" at ARENA.

See https://github.com/php/php-src/blob/master/ext/opcache/zend_persist_calc.c#L391

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

Nikita, can you please take a look.

------------------------------------------------------------------------
[2019-02-14 14:45:48] dmitry@php.net

"Typed properties" conflict with "preloading" (even if they are not used).

------------------------------------------------------------------------
[2019-02-13 19:56:55] mberchtold at gmail dot com

This is the preload.php script I'm using:

<?php
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);
            }
          }
          closedir($dh);
        }
      } 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);
        	}
      	}
      }
    }
  }
}
_preload(['C:\vendor\zendframework\zend-validator\src']);

------------------------------------------------------------------------
[2019-02-13 19:54:33] mberchtold at gmail dot com

To reproduce it, it is sufficient to preload the zend-validator\src folder from ZF3:
_preload(['C:\vendor\zendframework\zend-validator\src']);

------------------------------------------------------------------------
[2019-02-13 19:44:18] mberchtold at gmail dot com

Description:
------------
I'm testing PHP 7.4 (https://windows.php.net/downloads/snaps/ostc/7.4/2019-02-13/) 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:
https://github.com/zendframework/zend-validator/blob/master/src/File/NotExists.php

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:
https://github.com/zendframework/zend-validator/blob/master/src/File/NotExists.php

Expected result:
----------------
No crash.

Actual result:
--------------
Access violation.


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=77615&edit=1


Thread (8 messages)

« previous php.bugs (#219589) next »