|   | php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
| 
  [2016-01-11 18:24 UTC] gpointorama at gmail dot com
 Description:
------------
We are doing some tests before upgrading to php7 and found this change in behavior between php5 and php7:
setting
php_admin_value[error_reporting] = E_ALL & ~E_NOTICE
in some fpm pool configuration can be bypassed in user code calling error_reporting()
the php5 version we are using was:
PHP 5.5.9-1ubuntu4.14 (fpm-fcgi) (built: Oct 28 2015 01:38:24)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies
and the php7 one is from:
https://launchpad.net/~ondrej/+archive/ubuntu/php-7.0
PHP 7.0.2-1+deb.sury.org~trusty+1 (fpm-fcgi)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2015 Zend Technologies
Test script:
---------------
error_reporting(E_ALL); //in php5 this call have no effect and php_admin_value[error_reporting] wins over
$a = array();
echo $a['b']; //should not trigger: Notice: Undefined index: b, because error_reporting still be E_ALL & ~E_NOTICE
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits             | |||||||||||||||||||||||||||||||||||||
|  Copyright © 2001-2025 The PHP Group All rights reserved. | Last updated: Fri Oct 31 15:00:01 2025 UTC | 
I made a change to ZEND_FUNCTION(error_reporting)in zend_builtin_functions.c which corrects this error. I reverted this to something based on code in previous version of PHP. As I am not experienced in changing PHP, I cannot say if this is a good fix, but it establishes what the problem is. New code: ZEND_FUNCTION(error_reporting) { zval *err; int old_error_reporting; #ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS(), "|z", &err) == FAILURE) { return; } #else ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL Z_PARAM_ZVAL(err) ZEND_PARSE_PARAMETERS_END(); #endif old_error_reporting = EG(error_reporting); if(ZEND_NUM_ARGS() != 0) { zend_string *key = zend_string_init("error_reporting", sizeof("error_reporting")-1, 0); zend_string* value = zval_get_string(err); zend_alter_ini_entry(key, value, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME); zend_string_release(key); } RETVAL_LONG(old_error_reporting); }this is the required patch, ive talked about it on irc with php devs a while ago, a test for this should also be added to be sure does not happens again, it's obviusly a bug, someone at some point copy pasted the some wrong code from the utility functions instead of calling it, also there is some ppl that think the new backward incompatible and buggy behavior is right, it's funny please someone show some love to this bug :( @@ -673,38 +673,10 @@ ZEND_FUNCTION(error_reporting) old_error_reporting = EG(error_reporting); if (ZEND_NUM_ARGS() != 0) { zend_string *new_val = zval_get_string(err); - do { - zend_ini_entry *p = EG(error_reporting_ini_entry); - - if (!p) { - p = zend_hash_find_ptr(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING)); - if (p) { - EG(error_reporting_ini_entry) = p; - } else { - break; - } - } - if (!p->modified) { - if (!EG(modified_ini_directives)) { - ALLOC_HASHTABLE(EG(modified_ini_directives)); - zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0); - } - if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), p) != NULL)) { - p->orig_value = p->value; - p->orig_modifiable = p->modifiable; - p->modified = 1; - } - } else if (p->orig_value != p->value) { - zend_string_release(p->value); - } - - p->value = new_val; - if (Z_TYPE_P(err) == IS_LONG) { - EG(error_reporting) = Z_LVAL_P(err); - } else { - EG(error_reporting) = atoi(ZSTR_VAL(p->value)); - } - } while (0); + zend_string *ini_name; + ini_name = zend_string_init("error_reporting", sizeof("error_reporting") - 1, 0); + zend_alter_ini_entry(ini_name, new_val, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME); + zend_string_release(ini_name); } RETVAL_LONG(old_error_reporting);If we want to talk about a clean and elegant way to fix this mess with error handling in php then i can propose an error_reporting(E_ALL){... php code here ...} block to make clear and obvious the scope of the error_reporting settings....but that's another matter...A few thoughts from the peanut gallery: * What are the possible workarounds for this? Ideally ones that don't involve patching PHP. For example, maybe adding "disable_functions = error_reporting" but that'd add a bunch of E_WARNING's. Not ideal, are there others? * For clarity, does this PHP 7 change allow error_reporting(foo) but continue to disallow ini_set("error_reporting", foo) with php_admin_*? If so then that'd be weird and likely unintentional, right?> For example, maybe adding "disable_functions = error_reporting" but that'd add a bunch of E_WARNING's. Not ideal, are there others? Very bad idea. For example, Roundcube with "disable_functions = error_reporting" doesn't work... > For clarity, does this PHP 7 change allow error_reporting(foo) but continue to disallow ini_set("error_reporting", foo) with php_admin_*? If so then that'd be weird and likely unintentional, right? Code: echo "php_admin_value: " . ini_get("error_reporting") . "<br>"; ini_set("error_reporting", 8); echo "ini_set: " . ini_get("error_reporting") . "<br>"; error_reporting(8); echo "error_reporting: " . ini_get("error_reporting") . "<br>"; Return: php_admin_value: 2 ini_set: 2 error_reporting: 8 But there must be all "2". PHP 7.2.6