ID:               44053
 User updated by:  mark at metrofindings dot com
 Reported By:      mark at metrofindings dot com
 Status:           Open
 Bug Type:         Scripting Engine problem
 Operating System: linux
 PHP Version:      5.2.5
 New Comment:

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.


Previous Comments:
------------------------------------------------------------------------

[2008-02-05 19:33:14] 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"


------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=44053&edit=1

Reply via email to