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
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
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

Add a Patch

Pull Requests

Add a Pull Request

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-2021 The PHP Group
All rights reserved.
Last updated: Mon Oct 25 17:03:33 2021 UTC