You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(agent): wrap zend_try in a func to avoid clobbering (#703)
Calls to `call_user_function` (in PHP 8.0 and 8.1) and
`zend_call_method_if_exists` (in PHP 8.2+) need to be wrapped by the
`zend_try`/`zend_catch`/`zend_end_try` block, which use
[`setjmp`](https://linux.die.net/man/3/setjmp) and
[`longjmp`](https://linux.die.net/man/3/longjmp), because according to
[`call_user_func()`](https://www.php.net/manual/en/function.call-user-func.php):
> Callbacks registered with functions such as `call_user_func()` and
[`call_user_func_array()`](https://www.php.net/manual/en/function.call-user-func-array.php)
will not be called if there is an uncaught exception thrown in a
previous callback.
So if we call something that causes an exception, it will block us from
future calls that use `call_user_func` or `call_user_func_array`.
Valgrind showed the agent and/or the Zend engine wasn’t properly
cleaning up after such cases and newer compilers had issues with this
when compiling with any optimization and generated the following error:
```
error: variable ‘retval’ might be clobbered by ‘longjmp’ or ‘vfork’) [-Werror=clobbered]
```
PHP developers solve this problem by using an automatic variable to
store user function call result - see
[here](https://github.com/php/php-src/blob/master/main/streams/userspace.c#L335-L340)
for an example in PHP source code how zend_call_method_if_exists is
called.
This solution wraps `zend_try`/`zend_catch`/`zend_end_try` constructs in
a function to localize the `retval` and avoid variable clobbering.
0 commit comments