|   | php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
| 
  [2017-01-30 13:41 UTC] uli dot hecht at gmail dot com
 Description:
------------
This bug only appears on my Windows system and is very hard to reproduce. I can only reproduce it with Symfony-projects, however all of my Symfony projects are affected. It seems that the problem doesn't occur, as long as Opcache is disabled:
After loading the page in the browser about 5 to 10 times, entries of the result array of ReflectionClass::getInterfaceNames() contain unexpected data. As soon as the error appears, getInterfaceNames() will return the same (wrong) data for the same interface on every succeeding call, no matter which class is reflected.
For instance, today "\Serializable" has been affected. Instead of "\Serializable", getInterfaceNames() returned an entry containing "#[^/\\]*$#" everytime for a Symfony class implementing that interface. I defined an own class  implementing \Serialiazable (see test script) to check this, and got the same result:
    array(1) { [0]=> string(10) "#[^/\\]*$#" }
I'm running PHP as Apache 2.4 module. The error disappears, as soon as I restart the HTTP server. Then I have another 5 to 10 reloads until the problem re-appears with other interfaces being affected and other wrong random values being returned for those affected interfaces.
In 95% of the cases an "OutOfMemoryException" is thrown, because the string length is a few Gigabytes, making it difficult to determine the affected interface. For example, at the moment I'm writing this, "\IteratorAggregate" is the affected interface and I'm getting this output:
array(2) { [0]=> string(4294967296) "
Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 4294971392 bytes) in C:\Daten\Projekte\2016\dev\xxxxx-xxxxx\src\web\app_dev.php on line 12
(I just added this information in case somebody is having the same problems. In the beginning I always googled for OutOfMemoryException related topics)
Interestingly, in the "\Serializable"-case before, I could find the string of the corrupt entry ("#[^/\\]*$#") in another Symfony class variable that has nothing to do with the problem at all. So it seems that the corrupt entries are pointing to a random location in the memory.
Note: The test script (obviously) depends on the affected interface. To find out which interfaces are affected, I have to modify Symfony's DebugClassLoader temporarily. Symfony crashes here, when processing the results of getInterfaceNames(). As soon as the error occurs, the test script can be executed independently from the Symfony project in a separate PHP file.
This problem is really annoying, because I have to restart my HTTP server every few page reloads.
My specifications:
- Windows 7 x64
- Apache 2.4.23 win64 VC14 (from apachelounge.com)
- PHP 7.1.1 x64 TS
- Configure line: cscript /nologo configure.js "--enable-snapshot-build" "--enable-debug-pack" "--with-pdo-oci=c:\php-sdk\oracle\x64\instantclient_12_1\sdk,shared" "--with-oci8-12c=c:\php-sdk\oracle\x64\instantclient_12_1\sdk,shared" "--enable-object-out-dir=../obj/" "--enable-com-dotnet=shared" "--with-mcrypt=static" "--without-analyzer" "--with-pgo"
I'm having this problem for about a year now, so I can say that also older PHP7 versions are affected.
php.ini changes (My php.ini is based on php.ini-development):
- I'm using opcache with following php.ini settings:
    opcache.enable = 1
    opcache.enable_cli = 0
    opcache.memory_consumption = 128
    opcache.interned_strings_buffer = 8
    opcache.max_accelerated_files = 4000
- realpath_cache_size = 2M
- I increased limits (memory, upload file size, execution time, etc.)
- I enabled these extensions: bz2, curl, fileinfo, gs2, intl, mbstring, mysqli, openssl, pdo_mysql, soap, sockets, redis (only sometimes), opcache
Test script:
---------------
/* \Serializable being an affected interface */
    class DEBUGTEST implements \Serializable {
        public function serialize(){}
        public function unserialize($serialized){}
    }
    $drefl = new \ReflectionClass('\DEBUGTEST');
    $y = $drefl->getInterfaceNames();
    var_dump($y);
    die();
/* \IteratorAggregate being an affected interface */
    class DEBUGTEST implements \IteratorAggregate {
        public function getIterator() {}
    }
    $drefl = new \ReflectionClass('\DEBUGTEST');
    $y = $drefl->getInterfaceNames();
    var_dump($y);
    die();
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits             | |||||||||||||||||||||||||||||||||||||
|  Copyright © 2001-2025 The PHP Group All rights reserved. | Last updated: Fri Oct 31 19:00:02 2025 UTC | 
Was able to reproduce this issue running under 7.0.17 with Windows 7 and the latest 7.0 snapshot master as of today 3/23/17 (php-7.0-ts-windows-vc14-x64-r1517fdb. Environment - Windows 7 x64 - Apache 2.4.23 win64 VC14 (from apachelounge.com) - php-7.0.17-Win32-VC14-x64 (also tried 7.0-ts-windows-vc14-x64-r1517fdb) ------------------------------------------------------------------ test.php ------------------------------------------------------------------ // Test data class DUMMY implements \Serializable, \IteratorAggregate, \Countable, \ArrayAccess { public function serialize() {} public function unserialize($serialized) {} public function getIterator() {} public function offsetExists($offset) {} public function offsetGet($offset) {} public function offsetSet($offset, $value) {} public function offsetUnset($offset) {} public function count() {} } // Provoke error $cls = new \ReflectionClass('\DUMMY'); foreach ($cls->getInterfaceNames() as $interfaceName) { class_implements($interfaceName); // Failure here } Occurs under load as described, I simulated this with the Apache benchmark tool: ab -c 100 -n 10000 "http://localhost/test.php" Following error occurs in the error log: PHP Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 8318823012549873016 bytes) in D:\development\test.php on line 23