Bug #66429 [Opn]: Logic flaw in handling of empty Interned strings
Edit report at https://bugs.php.net/bug.php?id=66429&edit=1
ID: 66429
User updated by: Terry at ellisons dot org dot uk
Reported by: Terry at ellisons dot org dot uk
Summary: Logic flaw in handling of empty Interned strings
Status: Open
Type: Bug
Package: opcache
Operating System: N/A
PHP Version: master-Git-2014-01-06 (Git)
Block user comment: N
Private report: N
New Comment:
Sorry, I've just tested this on 5.5 and realised that I need
#if ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO
...
#endif
around my references to interned_empty_string. I'll post an updated patch tomorrow.
Previous Comments:
------------------------------------------------------------------------
[2014-01-06 23:27:17] Terry at ellisons dot org dot uk
Description:
------------
The opcache extenstion turns off PHP string interning and substitutes its own strategy for
collecting interned strings in its own SHM-based interned_strings hash during in
ZendAcclerator.c:zend_accel_init_shm(). It is then turned off in accel_shutdown().
Before and after these points in accel_startup() and accel_shutdown(), all interned strings created
and dtored should lie between the original CG(interned_strings_start) and CG(interned_strings_end).
Note that this list of local interned strings is non-trivial (typically some 2,000) comprising
interned_string representations of all builtin Zend and extension constants, function names and
methods. I call these built-in interned strings.
Between these same points all interned strings created and dtored should lie between
ZCSG(interned_strings_start) and ZCSG(interned_strings_end). I call these shared interned strings.
However, if a zval refering to a builtin interned string is dtored between accel_startup() and
accel_shutdown(), then the !IS_INTERNED() macro will return false as the address of the string lies
between original CG(interned_strings_start) and CG(interned_strings_end) and not between
ZCSG(interned_strings_start) and ZCSG(interned_strings_end). DTOR will then attempt to efree the
string which is invalid as the string wasn't emalloc'ed.
As long as the scope and lifetimes of the two sets of interned strings are disjoint this all works
fine. However, one optimization introduced in PHP-5.6 has been missed and that is with strings and
zvals created with the STR_EMPTY_ALLOC(), RETVAL_EMPTY_STRING() and ZVAL_EMPTY_STRING() macros.
These are all based on the CG(interned_empty_string) value and this is a built-in interned string.
If any of these are DTORed then the dtor will fail as described above. ZendAccelerator should
establish its own ZCSG(interned_empty_string) value to prevent this happening.
Test script:
---------------
php56 -r ''
(with opcache enabled)
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=66429&edit=1
Thread (3 messages)