php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #54054 Autoload not called in user-defined error handler function in case of E_STRICT
Submitted: 2011-02-19 14:39 UTC Modified: 2013-09-29 07:56 UTC
Votes:13
Avg. Score:4.2 ± 0.7
Reproduced:12 of 12 (100.0%)
Same Version:2 (16.7%)
Same OS:1 (8.3%)
From: morpika at vipmail dot hu Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.3.5 OS: FreeBSD 8.0
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: morpika at vipmail dot hu
New email:
PHP Version: OS:

 

 [2011-02-19 14:39 UTC] morpika at vipmail dot hu
Description:
------------
__autoload function is not called in user-defined error handler function in case of E_STRICT error. In case of any other type of errors (thet user-defined error handler function can handle) the autoload function is called properly.

Test script:
---------------
test.php:

<?php
set_error_handler('php_error');
function php_error($errno, $errcode) { t_class::t_function($errno, $errcode); }
function __autoload($class_name) { echo 'autoload called'; exit; }
require('nf.php');
?>

nf.php (to create an E_STRICT ERROR: Redefining already defined constructor):

<?php
class number_format {
public function __construct() {}
public function number_format($number) { echo number_format($number, 0, '.', '.'); }
}
?>

Expected result:
----------------
autoload called

Actual result:
--------------
Fatal error: Class 't_class' not found

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-09-14 11:43 UTC] phil at propcom dot co dot uk
This is still an issue.

The 2 test cases below should hopefully sum this up for you.

Case 1...

include() call fails and generates an E_WARNING
E_WARNING is caught by the error handler
Error handler attempts to use \Error class and calls the autoloader because it is not currently loaded

...Case 2

The included file (http://codepad.viper-7.com/xyCn8C) generates an E_STRICT
E_STRICT is caught by the error handler
Error handler attempts to use \Error class and fails with a fatal error WITHOUT calling the autoloader

The problem is that, in case 2, it is expected that the autoloader would be used to load the \Error class. This doesn't appear to be the case.



Case 1: http://codepad.viper-7.com/b065B1

Case 2: http://codepad.viper-7.com/qi5185
Included file (xyCn8C) in Case 2: http://codepad.viper-7.com/xyCn8C
 [2011-09-14 12:41 UTC] web at darrengordon dot net
The use of opcoding caching can cause this issue to not be reproducable.

Test steps:
------------
1. Enable opcode caching (APC), restart your httpd to ensure the opcode cache is clean.
2. Request testa.php to trigger the E_STRICT.

Result:
---
*error_handler(): "Declaration of Bar::baz() should be compatible with that of Foo::baz()"

Fatal error: Class 'Error' not found in /<path>/trigger_e_strict.php on line 3

3. Uncomment line #25: "include('doesntexist');" and re-request testa.php to trigger the E_WARNING.

Result:
---	
*error_handler(): "include(doesntexist): failed to open stream: No such file or directory"
*__autoload(): "Error"
*Error::output()
*error_handler(): "include(): Failed opening 'doesntexist' for inclusion 
(include_path='.:/<path>:/usr/share/php')"
*Error::output()
*error_handler(): "Declaration of Bar::baz() should be compatible with that of Foo::baz()"
*Error::output()

4. Recomment line #25: "include('doesntexist');" and re-request testa.php to trigger the E_STRICT.

Result:
---
*error_handler(): "Declaration of Bar::baz() should be compatible with that of Foo::baz()"
*_autoload(): "Error"
*Error::output()

Expected result:
----
Steps 2. and 4. should output the same result as the code is identical.

Actual result:
----
Steps 2. and 4. output different results.
Step 2. behaves according to the "Actual result" of bug #54054.
Step 4. behaves according to the Expected result" of bug #54054.

Notes:
----
This behaviour should be noted when reproducing bug #54054 as it will cause the issue to not be reproducable.

Environment:
----
PHP 5.3.2
Apache/2.2.14
Ubuntu 10.04.3 LTS

Code:
----

testa.php
---------
<?php
error_reporting(-1);

// Set error handler
set_error_handler('error_handler');

// Error handler
function error_handler($severity, $message)
{
	echo "*error_handler(): \"$message\"\n";
	
	return Error::output();
}

// Autoloader
function __autoload($class)
{
	echo "*__autoload(): \"$class\"\n";
	
	// Load class 'Error'
	eval("class $class { 
		public static function output() { echo '*' . __CLASS__ . '::output()\n'; } 
	}");
}

// Trigger E_WARNING - Uncomment to alter opcode cache
//include('doesntexist');

// Trigger E_STRICT
include('testb.php');
?>

testb.php
-----
<?php
// Trigger E_STRICT
class Foo { public function baz($var){} }
class Bar extends Foo { public function baz() {} }
?>
 [2012-12-27 09:41 UTC] nicolas dot grekas+php at gmail dot com
This bug is a duplicate of bug #42098.
 [2013-08-22 09:07 UTC] ota dot mares at gmail dot com
I have the same issue with a more complex setup using monolog, the custom 
monolog 
error handler and gelf as logger.

Instead of logging the message "Warning: The use statement with non-compound 
name 
'UnexpectedValueException' has no effect in ...IndexController.php on line 11" 
the 
php error handling hickups, resulting in following error: "Fatal error: Class 
'Gelf\Message' not found in ...IndexController.php on line 11". Please note that 
the above warning is never shown or logged in this case. All you get is a 
confusing fatal message.

In all other scenarios the logging works, which leads to the assumption that the 
autoloading never happens in the given case.
 [2013-08-29 15:21 UTC] tyrael@php.net
-Package: *Programming Data Structures +Package: Scripting Engine problem
 [2013-09-18 07:55 UTC] tony2001@php.net
-Status: Open +Status: Not a bug
 [2013-09-18 07:55 UTC] tony2001@php.net
Here's how it looks:
1) PHP tries to compile a file
2) an error is found and the error handler is triggered (but we're still in compilation 
phase)
3) since we're already in compiler, we can't call the compiler again - the compiler is 
not reentrant, so autoload is skipped.
4) class not found.
This behaviour is by design and isn't going to change without complete rewrite of 
the compiler (if ever).
 [2013-09-29 07:56 UTC] tyrael@php.net
Antony: how is this any different than including a file from the error handler or 
calling spl_autoload_call() manually there.
if your 3) is true(which was always the reasoning for this particular behavior), 
we shouldn't be allowed to do that as far as I understand.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Dec 02 10:01:30 2024 UTC