php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #81454 error_reporting() and ini_get('error_reporting') can get out of sync using @
Submitted: 2021-09-17 19:37 UTC Modified: -
From: daimona dot wiki at gmail dot com Assigned:
Status: Open Package: Scripting Engine problem
PHP Version: Irrelevant OS: Any
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: daimona dot wiki at gmail dot com
New email:
PHP Version: OS:

 

 [2021-09-17 19:37 UTC] daimona dot wiki at gmail dot com
Description:
------------
This bug is a direct consequence of bug #75924. That one essentially states that, starting with PHP 7, the @ operator affects the output of error_reporting(), but not that of ini_get('error_reporting').

Now, consider the following test case: https://3v4l.org/70QJY

For the PHP 7 examples, I'd expect error_reporting() and ini_get() to return the same value (-1) in "POST", but this is not the case.

AIUI, it happens because:
- error_reporting() and ini_get() are out of sync when testFunc() starts, per bug #75924
- error_reporting(0) syncs them again, as expected
- Same for error_reporting($orig)
- But then, when the silenced statement ends, only error_reporting() is restored (because only error_reporting() was changed by @, I guess)

This bug affects all versions of PHP starting from 7.0. PHP 8 is also affected, even though some numeric values are different.

Test script:
---------------
function testFunc() {
    print "INSIDE 1 er=" . error_reporting() . ' ini=' . intval( ini_get( 'error_reporting' ) ) . "\n";
    $orig = error_reporting( 0 );
    print "INSIDE 2 er=" . error_reporting() . ' ini=' . intval( ini_get( 'error_reporting' ) ) . "\n";
    error_reporting( $orig );
    print "INSIDE 3 er=" . error_reporting() . ' ini=' . intval( ini_get( 'error_reporting' ) ) . "\n";
}

print "PRE er=" . error_reporting() . ' ini=' . intval( ini_get( 'error_reporting' ) ) . "\n";
@testFunc();
print "POST er=" . error_reporting() . ' ini=' . intval( ini_get( 'error_reporting' ) ) . "\n";

Expected result:
----------------
PRE er=-1 ini=-1
INSIDE 1 er=0 ini=0
INSIDE 2 er=0 ini=0
INSIDE 3 er=0 ini=0
POST er=-1 ini=-1

Actual result:
--------------
PRE er=-1 ini=-1
INSIDE 1 er=0 ini=-1
INSIDE 2 er=0 ini=0
INSIDE 3 er=0 ini=0
POST er=-1 ini=0

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-09-19 15:48 UTC] antonino dot spampinato86 at gmail dot com
The @ operator will no longer silence fatal errors (E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR, E_PARSE). Error handlers that expect error_reporting to be 0 when @ is used, should be adjusted to use a mask check instead:

For consistency even the value 0, as it previously indicated error suppression. The php constants of the errors is a numerical sequence, a mask means from the single or the union of them.
 [2021-09-19 15:51 UTC] antonino dot spampinato86 at gmail dot com
For php >= 8 https://www.php.net/manual/en/migration80.incompatible.php
 [2021-09-19 21:07 UTC] antonino dot spampinato86 at gmail dot com
<?php
# different results for PHP 5.x and 8.x:
//-1 only works in 2s-complement numeric representations, ~0 in 1s-complement numeric representations
//ini_set('error_reporting', 2);
$a = array();
$a['ini_get'] = @ini_get('error_reporting');
if(is_string($a['ini_get'])) //return ini_get empty string for false or null, if undefined is default "null" prior 5.3 it's return bool false #42657
$a['ini_get'] = ini_get('error_reporting');
$a['error_reporting'] = @error_reporting();
if(is_int($a['error_reporting']))
$a['error_reporting'] = error_reporting();
$a['bug'] = @error_reporting();
$b = false; //function not work?
$c = null; //function disabled?
var_dump($a, @$b, @$c);

Expected result:
array(3) {
  ["ini_get"]=>
  string(2) "-1"
  ["error_reporting"]=>
  int(-1)
  ["bug"]=>
  int(-1)
}
bool(false)
NULL

php >= 8:
array(3) {
  ["ini_get"]=>
  string(2) "-1"
  ["error_reporting"]=>
  int(-1)
  ["bug"]=>
  int(4437)
}
bool(false)
NULL

php < 8:
array(3) {
  ["ini_get"]=>
  string(2) "-1"
  ["error_reporting"]=>
  int(-1)
  ["bug"]=>
  int(0)
}
bool(false)
NULL
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 16:01:28 2024 UTC