Become a Patron!

My Amazon wishlist can be found here.

Life Line

Adverse ABIs

After last week's release candidate I started receiving some bug reports that Xdebug nearly instantaneously crashed PHP. Upon further investigation, it turned out to only be a problem on macOS, which is good as that's not affecting everybody, but bad as I don't have a macOS machine to try to reproduce things on.

I did some screen sharing with Frédéric Marand in order to dive down what the problem was, but we couldn't really get to the problem. It looked like there was nothing really wrong, until Xdebug called the php_addslashes C function (which is the internal implementation of addslashes). This matched the exact same location as David Vuorio showed in his stack trace in the bug tracker.

Still tearing my hairs out, I contacted Nikita Popov to see if he knew whether there was anything special about php_addslashes. His reply:

I have some suspicions...

And his suspicion turned out to be right.

PHP 7.3 has received many optimisations. One of them is the use of specific CPU instructions to speed up certain tasks. In this case, the PCMPESTRM instruction is used to find whether a string has characters that need to be escaped.

Upon build time, PHP's ./configure script checks whether the CPU it is built on supports these newer CPU instructions. If so, it then uses some header magic to use a specialised version of php_addslashes. This works fine if both PHP and the extension that uses php_addslashes are compiled on the same machine. However, if PHP is compiled on a machine without support, and the extension (Xdebug) is compiled on a machine with support, then the ABI (calling convention) of the php_addslashes C function is different. A crash will then occur when the extension tries to call the PHP php_addslashes function "in the wrong way". And that is exactly what happened here: the PHP binary that came from Homebrew uses a different ABI then the Xdebug binary that users compiled themselves. Modifying the installed headers made the problem go away.

Nikita soon fixed this in the PHP 7.3 branch with a hack to make sure that the ABI among PHP 7.3 versions stays the same, and a proper fix for PHP 7.4 and later to prevent this situation from occurring in the feature. Xdebug works around it for PHP 7.3.0 and PHP 7.3.1. Instead of relying on PHP's implementation of php_addslashes (xdebug_add_slashes), it uses its own. It also uses its own implementations of php_base64_encode and php_base64_decode which exhibit a similar issue. As Xdebug's implementations are slightly modified to work better for Xdebug, there is a minimal performance improvement too.

Time for Release Candidate 2!

Comments

No comments yet

Add Comment

Name:
Email:

Will not be posted. Please leave empty instead of filling in garbage though!
Comment:

Please follow the reStructured Text format. Do not use the comment form to report issues in software, use the relevant issue tracker. I will not answer them here.


All comments are moderated