php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #81652 The value of error_reporting() gets overridden
Submitted: 2021-11-23 11:45 UTC Modified: 2021-11-24 14:03 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: joupicky at gmail dot com Assigned:
Status: Closed Package: opcache
PHP Version: 8.0.13 OS: Ubuntu 20.04.3 LTS
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
49 - 18 = ?
Subscribe to this entry?

 
 [2021-11-23 11:45 UTC] joupicky at gmail dot com
Description:
------------
The value of error_reporting() function (and global error reporting setting) gets overridden when a native PHP function such as random_int() or filemtime() gets called with a suppress "@" operator and assigned to a class variable.

I am running PHP Version 8.0.13 with the latest Apache2. I was able to reproduce this also when ran as FPM. I was not able to reproduce this when called as CLI. I am using a precompiled binaries from https://launchpad.net/~ondrej/+archive/ubuntu/php/. I was not able to reproduce this on PHP7.4 when install via Ubuntu repos. This might be only relevant to the build from that repository (which is used by many people AFAIK).

Test script:
---------------
<?php

error_reporting(E_ALL);

class Foo
{
    public $a;

    public function bar() {
        $this->a = (true) ? @random_int(0, 100) : false;
    }
}

var_dump(error_reporting()); //int(32767) = E_ALL
$c = new Foo();

$c->bar();

var_dump(error_reporting()); //random int

Expected result:
----------------
int(32767)
int(32767) 

Actual result:
--------------
int(32767)
int(5) //random int

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-11-23 13:20 UTC] cmb@php.net
I cannot reproduce this with PHP 8.0.13 with Apache 2.4 (mod_php)
on Windows.
 [2021-11-23 21:49 UTC] antonino dot spampinato86 at gmail dot com
I doubt this is a valid expression for your ternary operator, also with this code the integer value change for error_reporting occurs?

error_reporting(E_ALL);

class Foo
{
    public $a;

    public function seta($a) {
        $b = @random_int(16, 16);
            if(is_int($b))
            $this->a = $b;
        return $a;
}
    public function numbera() {
    return $this->a;
}
}

$c = new Foo();
$c->seta(0);
$var = $c->numbera();
if($var != 16)
echo 'bug' . PHP_EOL;
else
echo 'normal' . PHP_EOL;
var_dump($var, error_reporting(), @error_reporting());

The @ operator will no longer silence fatal errors (E_ERROR == 1, E_CORE_ERROR == 4, E_COMPILE_ERROR == 64, E_USER_ERROR == 256, E_RECOVERABLE_ERROR == 4096, E_PARSE == 4)
https://www.php.net/manual/en/migration80.incompatible.php
 [2021-11-23 23:47 UTC] james at gogo dot co dot nz
I was able to reproduce this in a fresh Ubuntu 20.04 setup, here are reproduction steps which should work starting from spinning up fresh Ubuntu 20.04 on Amazon EC2.

Interesting, the issue doesn't always happen if you hit the file immediately after creating it, even if you hit it multiple times immediately after creating it, a small delay is necessary.

Test Process
--------------------



sudo su
add-apt-repository ppa:ondrej/php
apt-get update
apt-get upgrade
apt-get install php8.0-fpm apache2 
a2enmod proxy_fcgi
rm /etc/apache2/sites-enabled/000-default.conf
cat /etc/apache2/sites-available/000-default.conf | grep -v "</VirtualHost>" > /etc/apache2/sites-enabled/000-default.conf
cat >>/etc/apache2/sites-enabled/000-default.conf <<'EOF'
   <FilesMatch "\.php$">
    <If "-f %{REQUEST_FILENAME}">
        SetHandler "proxy:unix:/var/run/php/php8.0-fpm.sock|fcgi://localhost/"
    </If>
  </FilesMatch>
</VirtualHost>
EOF

service apache2 restart

cat >/var/www/html/test-1.php <<'EOF'
<?php

error_reporting(E_ALL);

class Foo
{
    public $a;

    public function bar() {
        $this->a = (true) ? @random_int(0, 100) : false;
    }
}


echo "Should Equal 32767: " . error_reporting() . "\n";

$c = new Foo();
$c->bar();

echo "Should Equal 32767: " . error_reporting() . "\n";

EOF

echo "Sleeping 2 seconds to more reliably trigger the issue..."
sleep 2
for x in 1 2 3 4 ; do curl http://localhost/test-1.php; done



----------
 [2021-11-23 23:58 UTC] james at gogo dot co dot nz
I'll add also that the test case can be simplified to

----------

<?php

error_reporting(E_ALL);

echo "Should Equal 32767: " . error_reporting() . "\n";

$a = true;
$b = $a ? @random_int(0,100) : false;

echo "Should Equal 32767: " . error_reporting() . "\n";

----------


It seems to the ternary which is the critical factor in producing the error.
 [2021-11-24 00:03 UTC] james at gogo dot co dot nz
Final note, I can also reproduce in PHP 8.1 (adjust reproduction script as appropriate).
 [2021-11-24 11:34 UTC] cmb@php.net
Do you have OPcache enabled?  Maybe even JIT?  Is it reproducible
without OPcache?
 [2021-11-24 11:36 UTC] nikic@php.net
-Status: Open +Status: Verified -Package: Unknown/Other Function +Package: opcache
 [2021-11-24 11:36 UTC] nikic@php.net
I can repro with opcache.
 [2021-11-24 14:03 UTC] nikic@php.net
The QM_ASSIGN to T0 is eliminated, even though there is a read of T0 in between:

Foo::bar:
     ; (lines=10, args=0, vars=0, tmps=2, ssa_vars=3, no_loops)
     ; (after dce pass)
     ; /home/nikic/php/php-src/t484.php:6-8
     ; return  [null] RANGE[0..0]
BB0:
     ; start exit lines=[0-9]
     ; level=0
0000 #0.T0 [long] = BEGIN_SILENCE
0001 INIT_FCALL 2 112 string("random_int")
0002 SEND_VAL int(0) 1
0003 SEND_VAL int(100) 2
0004 #1.V1 [long] = DO_ICALL
0005 END_SILENCE #0.T0 [long]
0006 #2.T0 [long] = QM_ASSIGN #1.V1 [long]
0007 ASSIGN_OBJ THIS string("a")
0008 OP_DATA #2.T0 [long]
0009 RETURN null

Foo::bar:
     ; (lines=9, args=0, vars=0, tmps=2, ssa_vars=3, no_loops)
     ; (after dfa pass)
     ; /home/nikic/php/php-src/t484.php:6-8
     ; return  [null] RANGE[0..0]
BB0:
     ; start exit lines=[0-8]
     ; level=0
0000 #0.T0 [long] = BEGIN_SILENCE
0001 INIT_FCALL 2 112 string("random_int")
0002 SEND_VAL int(0) 1
0003 SEND_VAL int(100) 2
0004 #2.T0 [long] = DO_ICALL
0005 END_SILENCE #0.T0 [long]
0006 ASSIGN_OBJ THIS string("a")
0007 OP_DATA #2.T0 [long]
0008 RETURN null
 [2021-11-24 14:21 UTC] git@php.net
Automatic comment on behalf of nikic
Revision: https://github.com/php/php-src/commit/be271f277eb5a9a3fc35f20bffb85b0d4957f4a6
Log: Fix bug #81652
 [2021-11-24 14:21 UTC] git@php.net
-Status: Verified +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Mar 29 02:01:30 2024 UTC