php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #44053 Core exceptions are actually E_WARNINGs first
Submitted: 2008-02-05 19:33 UTC Modified: 2008-02-24 19:59 UTC
Votes:4
Avg. Score:3.8 ± 0.4
Reproduced:3 of 3 (100.0%)
Same Version:1 (33.3%)
Same OS:2 (66.7%)
From: mark at metrofindings dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.2.5 OS: linux
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
8 + 18 = ?
Subscribe to this entry?

 
 [2008-02-05 19:33 UTC] mark at metrofindings dot com
Description:
------------
Core exceptions, those generated by core classes in the PHP engine 
itself and not user defined PHP code, are treated exactly as 
E_WARNING errors before any exception related routines are called 
when a custom error handler is being used.

This is a problem on 2 fronts: 
  1.  It is different than user generated exceptions (throw new 
Exception())
  2.  It is impossible to distinguish a core exception and a true 
E_WARNING in a custom error handler (set_error_handler()).


The zend engine portion of the error handling code does not respect 
PG(error_handling) settings, like EH_THROW.  The Zend engine portion 
of error handling (zend_error) calls any user defined error 
handlers, *then* it calls php_error_cb (which properly checks for 
throwable exceptions).

Here is a patch to php-5.2.5/main/main.c to check for exceptions 
before calling zend's "PG(error_handling) unaware" error routine.

--- orig-5.2.5/main/main.c      2008-02-05 14:14:51.000000000 -0500
+++ php-5.2.5/main/main.c       2008-02-05 14:09:05.000000000 -0500
@@ -717,9 +715,35 @@
               ZVAL_STRINGL(tmp, buffer, buffer_len, 1);
               
zend_hash_update(EG(active_symbol_table), "php_errormsg", 
sizeof("php_errormsg"), (void **) &tmp, sizeof(zval *), NULL);
        }
-       efree(buffer);
 
-       php_error(type, "%s", message);
+       //throw exceptions first before nomal zend_error
+       if (PG(error_handling) == EH_THROW && !EG(exception)) {
+              switch (type) {
+                     case E_ERROR:
+                     case E_CORE_ERROR:
+                     case E_COMPILE_ERROR:
+                     case E_USER_ERROR:
+                     case E_PARSE:
+                            /* fatal errors are real errors and 
cannot be made exceptions */
+                            break;
+                     case E_STRICT:
+                            /* for the sake of BC to old damaged 
code */
+                            break;
+                     case E_NOTICE:
+                     case E_USER_NOTICE:
+                            /* notices are no errors and are not 
treated as such like E_WARNINGS */
+                            break;
+                     default:
+                            /* throw an exception if we are in 
EH_THROW mode
+                             * but DO NOT overwrite a pending 
exception
+                             */
+                            
zend_throw_error_exception(PG(exception_class), buffer, 0, type 
TSRMLS_CC);
+              }
+       } else {
+              php_error(type, "%s", message);
+       }
+
+       efree(buffer);
        efree(message);
 }
 /* }}} */

--end of patch--


Reproduce code:
---------------
<?php

function handleError($n, $m, $f, $l) {
    //no difference between excpetions and E_WARNING
    echo "user error handler: e_warning=".E_WARNING."  num=".$n." msg=".$m." line=".$l."\n";
    return true;
    //change to return false to make the "catch" block execute;
}
set_error_handler('handleError');
//turn off to make try/catch work normally

//comment this whole try/catch out to see new DateTimeZone outside of a try / catch
//behavior is the same if you have set a custom error handler

//echo new DateTimeZone(1202229163);
try {
    $z = new DateTimeZone(1202229163);
} catch (Exception $e) {
    echo "caught exception\n\n";
}


Expected result:
----------------
"caught exception\n\n";


Actual result:
--------------
"user error handler: e_warning=2  num=2 
msg=DateTimeZone::__construct(): Unknown or bad timezone 
(1202229163) line=15"

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-02-05 19:41 UTC] mark at metrofindings dot com
Although, at first glace, this bug appears to be the same as 43377 
(http://bugs.php.net/bug.php?id=43377), it is not.  Bug 43377 is 
referring to a crash and was later reopened because all exceptions 
are caught be the user defined error handler.  I feel that the core 
problem is not reflected clearly enough in 43377 and it warrants a 
new bug since the original problem of that bug was fixed.
 [2008-02-24 19:59 UTC] jani@php.net
Duplicate of (open) bug #43377 so bogus.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 05:01:29 2024 UTC