php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79382 Cannot redeclare disabled function
Submitted: 2020-03-13 23:11 UTC Modified: 2020-04-30 07:54 UTC
From: admin at franceserv dot fr Assigned: nikic (profile)
Status: Closed Package: *General Issues
PHP Version: 7.3.15 and 7.4 OS: Linux
Private report: No CVE-ID: None
 [2020-03-13 23:11 UTC] admin at franceserv dot fr
Description:
------------
Hello,

Several websites are affected (Wordpress, NextCloud, PMB, Phpbb etc ...) on PHP 7.3.x till this version (7.3.15) and same with PHP 7.4 till now since several month.

The problem isn't present with PHP 7.2.x and lower.

The affected function is : if (!function_exists('getallheaders'))

With PHP 7.3 and 7.4 the following error is reported :
Fatal error: Cannot redeclare getallheaders() in ...

With exactly the same website without modification files the problem is not present on PHP 7.2 and lower.

Sample error message on PHP 7.3 and 7.4 :

Nextcloud : Fatal error: Cannot redeclare getallheaders() in /home/httpd/*/*/*/*/*/3rdparty/ralouphie/getallheaders/src/getallheaders.php on line 10

PhpBB : /home/httpd/*/*/*/*/*/forum/vendor/ralouphie/getallheaders/src/getallheaders.php on line 10

PMB : /home/httpd/*/*/*/*/*/includes/apache_functions.inc.php on line 10

Wordpress etc ...


All web developers are saying to rename the function "function getallheaders()" to avoid this error message ... which is not possible to everybody which are not developers ...

I'm using PHP 7.2, 7.3 and 7.4 on PHP-FPM with compilation install.

Someone could solve this problem which become more visible since people are upgrading their website to PHP 7.3 and + ?

Thank you in advance.

Actual result:
--------------
Fatal error: Cannot redeclare getallheaders() in ...

Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-03-13 23:35 UTC] bugreports at gmail dot com
developers simply need to learn that it's a terrible idea to taint the global namespace with random *unprefixed* userland functions

eveniif the function_exists() hack would work what makes you thinking that your handcrafted function is signature and *behavior" compatible?
 [2020-03-14 02:49 UTC] daverandom@php.net
Reading through the docs for the opcache ini settings[1] I note that the default value for opcache.optimization_level was changed in 7.3 to remove a flag, and a brief wander through the source reveals that the flag in question acquired new meaning between 7.2 and 7.3[2], and is also described as "unsafe", as is one of its neighbours that was removed from the default in 5.6.18. Hypothetically speaking, if one were to set up a new PHP installation by, say, copy-pasting the same ini files that originate in ancient history and have been passed from version to version since PHP 5, and hypothetically they maybe had buggered about with opcache related settings at some point and "turned everything on to make it faster", then hypothetically they might end up in a situation where those unsafe flags are set. Hypothetically.

I could be way off base there, but whatever is going on this has opcache fingerprints all over it. The fact that you are consistently seeing the same issue across many point releases in two minor version branches indicates that this is a config/environment issue. As such, the best place to start would be to conduct a thorough review of the active PHP configuration (i.e. phpinfo()), paying particularly close attention to opcache.

I feel like this is stating the obvious, but if were the case that multiple large scale foss projects had been fundamentally incompatible with new releases of PHP for the last 14+ months, someone would probably have noticed before now.

[1] https://www.php.net/manual/en/opcache.configuration.php
[2] https://github.com/php/php-src/commit/a02a126d54077d1f2f3c9a54a00a7e75d5b8f562#diff-18518eac33b6061b9da5d72d4637417a
 [2020-03-14 03:45 UTC] admin at franceserv dot fr
You have right, this problem is strange because I don't find it into bugs.php.net after so much long time. Thank you about the idea to check opcache, I disabled it temporary for testing but the problem was still here ...

I will continue to check my configuration but it don't seem to be related with opcache ... if someone have an idea and solved this problem on his configuration it's interest me ...
 [2020-03-14 08:48 UTC] nikic@php.net
I doubt this is opcache related. PHP 7.3 added getallheaders() for the FPM SAPI and the code also tries to define this function. You mention that there is a function_exists check, which should have prevented this. Can you share what the file that containts the getallheaders() declaration looks like?
 [2020-03-14 12:36 UTC] admin at franceserv dot fr
Yes exactly, the file is this one :
https://github.com/ralouphie/getallheaders/blob/develop/src/getallheaders.php

The condition "if (!function_exists('getallheaders'))" isn't checked and I need (same for few people over Internet too) rename the function "function getallheaders()" to "function _something_different_here_getallheaders()" to avoid the problem ...

A friend is using PHP 7.4 and he don't have this problem, but I don't know where to look because a configuration which change behavior of the function "function_exists()" is very strange.
 [2020-03-14 13:20 UTC] admin at franceserv dot fr
-PHP Version: 7.3.15 +PHP Version: 7.3.15 and 7.4
 [2020-03-14 13:20 UTC] admin at franceserv dot fr
My friend and me found the BUG :)

When the function "getallheaders" is disabled with disable_functions in php.ini, the function isn't visible by function_exists() but if we redeclare it, it's raise an error (instead a disabled function warning).

We are thinking it's really a bug because before 7.3 the behavior isn't same.

Could you check on your side please with PHP 7.3.x or 7.4.x ?
 [2020-03-14 14:14 UTC] admin at franceserv dot fr
This strange behavior seem to exist since 13 years at least :
https://www.php.net/manual/fr/function.function-exists.php#67947

When a function is disabled, if we check this function with function_exists() it's reply "don't exist", but if we are trying to declare the function it's reply "exist already". Funny :)
 [2020-03-14 14:22 UTC] bugreports at gmail dot com
"disable_functions" should throw an exception when a disabled function is called so one can handle it proper without spread *slow and expensive* function exists into the codebase - try/catch is much faster in cases where it don't throw

such compat layers defining a function which is part of a newer php release should go into a include file because code like below would be completly optimized out by opcache given the constant nature known at "compile time"

if(PHP_VERSION_ID < 70300)
{
 require 'php73.inc.php';
}
 [2020-03-14 14:27 UTC] bugreports at gmail dot com
that would also work better if you don't want a seperated include file which could be thrown away all togehter after deciding no longer support anything below PHP 7.3

on newer php versions this would also optimized out completly and avoid the issue of that bugreport as well as the terrible runtime overhead of function_exists()

if(PHP_VERSION_ID < 70300))
{
 function getallheaders()
 {
 }
}
 [2020-03-17 09:16 UTC] nikic@php.net
This is a pretty interesting case. I'm not sure what the correct behavior for this is.

Should we be allowing redefinition of disabled functions? Might be rather problematic technically.

Things would be a lot clearer here if disabled functions were simply completely removed, rather than replaced with a dummy implementation.
 [2020-03-17 12:07 UTC] cmb@php.net
It seems to me that function_exists() should return true, even if
the function is disabled.
 [2020-03-17 12:32 UTC] bugreports at gmail dot com
> It seems to me that function_exists() should return true, 
> even if the function is disabled

only if you provide a dedicated function or trow exceptions when disabled functions are called because otherwise you can't write any code which handles the situation correctly
 [2020-04-27 12:05 UTC] nikic@php.net
-Summary: Fatal error: Cannot redeclare getallheaders() in ... +Summary: Cannot redeclare disabled function
 [2020-04-27 12:13 UTC] nikic@php.net
The following pull request has been associated:

Patch Name: Completely remove disabled functions
On GitHub:  https://github.com/php/php-src/pull/5473
Patch:      https://github.com/php/php-src/pull/5473.patch
 [2020-04-30 07:54 UTC] nikic@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: nikic
 [2020-04-30 07:54 UTC] nikic@php.net
Fixed in PHP 8 by https://github.com/php/php-src/commit/53eee290b6f5ca531aef19885a392c939013ce36. It will now be possible to redefine disabled functions.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Fri May 29 17:01:40 2020 UTC