Bug #81096 [Ver]: Inconsistent opcache behavior with variables passed by reference to mysqli
Edit report at https://bugs.php.net/bug.php?id=81096&edit=1
ID: 81096
Updated by: nikic@php.net
Reported by: nickdnk at hotmail dot com
Summary: Inconsistent opcache behavior with variables passed
by reference to mysqli
Status: Verified
Type: Bug
Package: opcache
Operating System: Linux/docker
PHP Version: 8.0.6
Block user comment: N
Private report: N
New Comment:
Reduced:
<?php
function test() {
escape_x($x);
$x = 0;
modify_x();
return (int) $x;
}
function escape_x(&$x) {
$GLOBALS['x'] =& $x;
}
function modify_x() {
$GLOBALS['x']++;
}
var_dump(test());
Previous Comments:
------------------------------------------------------------------------
[2021-06-06 12:25:03] nickdnk at hotmail dot com
I would like to add that I am well aware that this code might not make a lot of sense, and that it
can be "fixed" quite easily by changing a few lines, but that's not the point. The
point is that there is a difference between PHP 7 and 8 which does not appear to be documented
anywhere, and I don't know what other issues this might cause.
------------------------------------------------------------------------
[2021-06-01 18:43:11] nickdnk at hotmail dot com
Description:
------------
Hello
I have a hard time describing what the problem here actually is, as I'm unsure of the root
cause. I have created a complete docker-compose setup that demonstrates the behavior, which is
available here: https://github.com/nickdnk/php-bug-demo
Clone it and run docker-compose up -d, wait for the containers to boot and composer to run (just
wait like 20 seconds or look at the container logs) then navigate to localhost:8001 for PHP 8.0.6
and localhost:8002 for PHP 7.4.15. Notice that the output is not identical and that PHP 8 got it
wrong.
Test script:
---------------
https://github.com/nickdnk/php-bug-demo
See the src/Test.php class. I pass $bind_integer by reference to $stmt->bind_result(), then set
it to 0 and call fetch(). Removing the "set to 0"-line causes the problem to go away, but
that does not explain what's going on or why this changed between 7 and 8.
The reason I use the Container class to return it is that if I read the variable, error_log or
var_dump it directly, it behaves as expected, which is very weird (?). Removing the (int) cast also
causes it to behave as expected.
Disabling opcache "fixes" the bug, so it also is not present when using Xdebug, which
makes it very hard to debug (and reproduce, mind you), hence the kind of complicated setup to
demonstrate it.
If you modify the scripts (for debugging purposes), navigate to localhost:8001/opcache or
localhost:8002/opcache to reset the opcache. Otherwise you would have to restart the web containers.
The PHP images used are the official ones from https://hub.docker.com/_/php with Composer, MySQLi, PDO etc.
added to them, so everything is more or less default. I only changed the opcache configuration as
visible in the php.ini file attached to the containers, as this is not enabled by default. You could
probably take some of these lines away though:
FROM php:8.0.6-apache # or 7.4.15
RUN apt-get update && \
apt-get install -y libpng-dev \
libjpeg-dev \
libfreetype6-dev \
libzip-dev \
git \
zip \
unzip \
mariadb-client
RUN docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/
RUN docker-php-ext-install \
mysqli \
gd \
exif \
zip \
pdo_mysql \
bcmath
RUN php -r "readfile('http://getcomposer.org/installer');" |
php -- --install-dir=/usr/bin/ --filename=composer && \
apt-get -y autoremove && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=81096&edit=1
Thread (8 messages)