I have a PHP extension that wraps or replaces function calls. This
extension has worked successfully with minimal changes between php versions
from PHP 5.1 through PHP 5.4. However, my attempts to port this extension
to PHP 5.5 have failed in one case, which makes we wonder about my other
successes with PHP 5.5.
I have figured out that in order to get access to the incoming actual
parameters for a hooked function I need to indirect through
->prev_execute_data iff the arguments pointer on the topmost frame is null.
Here's the scenario where I segfault:
I rebind zend_execute_ex to point to my executor. For most code paths my
executor does:
(a) gathers some profiling data;
(b) may call 0 or more times to other php functions using the
call_user_function_ex entry point into zend;
(c) turns around and calls execute_ex (zend_execute_data *ed), with the
same value of ed that my executor was given and so apparently correctly
executes the original function in what I presume is the correct evaluation
context.
However, if I do not do step (c) to execute the intended function, then
shortly after my executor returns I get a segfault in
zend_vm_stack_get_arg_ex (zend_execute.h line 320 from php 5.5.3), called
by zend_vm_stack_get_arg, called by ZEND_RECV_SPEC_HANDLER. The location
of the segfault has been seen to move around, and, for example, has been
observed to happen when the number of local slots to clear in a
clear_multiple is the bogus value 0x5a5a5a5a (which says, obviously,
there's memory corruption).
The discussions here
http://www.php.net/manual/en/migration55.internals.phpdo not provide
enough insight as to the changes in zend and how the
extension authors need to adjust for these changes.
Is there another working extension that does similar things that I can
study, or other guidelines to consult?
I note that Julienn Salleyron reported similar issues with his AOP work,
but that work contains a lot of code very specific to the implementation of
zend itself, and so from my position looks to be "too complex".
--
Robert Henry, New Relic