From:             mark at metrofindings dot com
Operating system: linux
PHP version:      5.2.5
PHP Bug Type:     Scripting Engine problem
Bug description:  Core exceptions are actually E_WARNINGs first

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 bug report at http://bugs.php.net/?id=44053&edit=1
-- 
Try a CVS snapshot (PHP 4.4): 
http://bugs.php.net/fix.php?id=44053&r=trysnapshot44
Try a CVS snapshot (PHP 5.2): 
http://bugs.php.net/fix.php?id=44053&r=trysnapshot52
Try a CVS snapshot (PHP 5.3): 
http://bugs.php.net/fix.php?id=44053&r=trysnapshot53
Try a CVS snapshot (PHP 6.0): 
http://bugs.php.net/fix.php?id=44053&r=trysnapshot60
Fixed in CVS:                 http://bugs.php.net/fix.php?id=44053&r=fixedcvs
Fixed in release:             
http://bugs.php.net/fix.php?id=44053&r=alreadyfixed
Need backtrace:               http://bugs.php.net/fix.php?id=44053&r=needtrace
Need Reproduce Script:        http://bugs.php.net/fix.php?id=44053&r=needscript
Try newer version:            http://bugs.php.net/fix.php?id=44053&r=oldversion
Not developer issue:          http://bugs.php.net/fix.php?id=44053&r=support
Expected behavior:            http://bugs.php.net/fix.php?id=44053&r=notwrong
Not enough info:              
http://bugs.php.net/fix.php?id=44053&r=notenoughinfo
Submitted twice:              
http://bugs.php.net/fix.php?id=44053&r=submittedtwice
register_globals:             http://bugs.php.net/fix.php?id=44053&r=globals
PHP 3 support discontinued:   http://bugs.php.net/fix.php?id=44053&r=php3
Daylight Savings:             http://bugs.php.net/fix.php?id=44053&r=dst
IIS Stability:                http://bugs.php.net/fix.php?id=44053&r=isapi
Install GNU Sed:              http://bugs.php.net/fix.php?id=44053&r=gnused
Floating point limitations:   http://bugs.php.net/fix.php?id=44053&r=float
No Zend Extensions:           http://bugs.php.net/fix.php?id=44053&r=nozend
MySQL Configuration Error:    http://bugs.php.net/fix.php?id=44053&r=mysqlcfg

Reply via email to