PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - Zend - zend_exceptions.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 370 416 88.9 %
Date: 2015-05-21 Functions: 37 40 92.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2015 Zend Technologies Ltd. (http://www.zend.com) |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 2.00 of the Zend license,     |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.zend.com/license/2_00.txt.                                |
      11             :    | If you did not receive a copy of the Zend license and are unable to  |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@zend.com so we can mail you a copy immediately.              |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16             :    |          Marcus Boerger <helly@php.net>                              |
      17             :    |          Sterling Hughes <sterling@php.net>                          |
      18             :    |          Zeev Suraski <zeev@zend.com>                                |
      19             :    +----------------------------------------------------------------------+
      20             : */
      21             : 
      22             : /* $Id$ */
      23             : 
      24             : #include "zend.h"
      25             : #include "zend_API.h"
      26             : #include "zend_builtin_functions.h"
      27             : #include "zend_interfaces.h"
      28             : #include "zend_exceptions.h"
      29             : #include "zend_vm.h"
      30             : #include "zend_dtrace.h"
      31             : #include "zend_smart_str.h"
      32             : 
      33             : static zend_class_entry *base_exception_ce;
      34             : static zend_class_entry *default_exception_ce;
      35             : static zend_class_entry *error_exception_ce;
      36             : static zend_class_entry *engine_exception_ce;
      37             : static zend_class_entry *parse_exception_ce;
      38             : static zend_class_entry *type_exception_ce;
      39             : static zend_object_handlers default_exception_handlers;
      40             : ZEND_API void (*zend_throw_exception_hook)(zval *ex);
      41             : 
      42        2460 : void zend_exception_set_previous(zend_object *exception, zend_object *add_previous)
      43             : {
      44             :     zval tmp, *previous, zv, *pzv, rv;
      45             : 
      46        2460 :         if (exception == add_previous || !add_previous || !exception) {
      47        2444 :                 return;
      48             :         }
      49          16 :         ZVAL_OBJ(&tmp, add_previous);
      50          16 :         if (!instanceof_function(Z_OBJCE(tmp), base_exception_ce)) {
      51           0 :                 zend_error_noreturn(E_CORE_ERROR, "Cannot set non exception as previous exception");
      52             :                 return;
      53             :         }
      54          16 :         ZVAL_OBJ(&zv, exception);
      55          16 :         pzv = &zv;
      56             :         do {
      57          16 :                 previous = zend_read_property(base_exception_ce, pzv, "previous", sizeof("previous")-1, 1, &rv);
      58          16 :                 if (Z_TYPE_P(previous) == IS_NULL) {
      59          16 :                         zend_update_property(base_exception_ce, pzv, "previous", sizeof("previous")-1, &tmp);
      60          16 :                         GC_REFCOUNT(add_previous)--;
      61          16 :                         return;
      62             :                 }
      63           0 :                 pzv = previous;
      64           0 :         } while (pzv && Z_OBJ_P(pzv) != add_previous);
      65             : }
      66             : 
      67         633 : void zend_exception_save(void) /* {{{ */
      68             : {
      69         633 :         if (EG(prev_exception)) {
      70           4 :                 zend_exception_set_previous(EG(exception), EG(prev_exception));
      71             :         }
      72         633 :         if (EG(exception)) {
      73          16 :                 EG(prev_exception) = EG(exception);
      74             :         }
      75         633 :         EG(exception) = NULL;
      76         633 : }
      77             : /* }}} */
      78             : 
      79       21934 : void zend_exception_restore(void) /* {{{ */
      80             : {
      81       21934 :         if (EG(prev_exception)) {
      82          16 :                 if (EG(exception)) {
      83           3 :                         zend_exception_set_previous(EG(exception), EG(prev_exception));
      84             :                 } else {
      85          13 :                         EG(exception) = EG(prev_exception);
      86             :                 }
      87          16 :                 EG(prev_exception) = NULL;
      88             :         }
      89       21934 : }
      90             : /* }}} */
      91             : 
      92        4585 : ZEND_API void zend_throw_exception_internal(zval *exception) /* {{{ */
      93             : {
      94             : #ifdef HAVE_DTRACE
      95             :         if (DTRACE_EXCEPTION_THROWN_ENABLED()) {
      96             :                 if (exception != NULL) {
      97             :                         DTRACE_EXCEPTION_THROWN(Z_OBJ_P(exception)->ce->name->val);
      98             :                 } else {
      99             :                         DTRACE_EXCEPTION_THROWN(NULL);
     100             :                 }
     101             :         }
     102             : #endif /* HAVE_DTRACE */
     103             : 
     104        4585 :         if (exception != NULL) {
     105        2448 :                 zend_object *previous = EG(exception);
     106        2448 :                 zend_exception_set_previous(Z_OBJ_P(exception), EG(exception));
     107        2448 :                 EG(exception) = Z_OBJ_P(exception);
     108        2448 :                 if (previous) {
     109           8 :                         return;
     110             :                 }
     111             :         }
     112        4577 :         if (!EG(current_execute_data)) {
     113          38 :                 if (exception && Z_OBJCE_P(exception) == parse_exception_ce) {
     114          32 :                         return;
     115             :                 }
     116           6 :                 if(EG(exception)) {
     117           6 :                         zend_exception_error(EG(exception), E_ERROR);
     118             :                 }
     119           0 :                 zend_error_noreturn(E_CORE_ERROR, "Exception thrown without a stack frame");
     120             :         }
     121             : 
     122        4539 :         if (zend_throw_exception_hook) {
     123           0 :                 zend_throw_exception_hook(exception);
     124             :         }
     125             : 
     126       12209 :         if (!EG(current_execute_data)->func ||
     127        4534 :             !ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
     128        3136 :             (EG(current_execute_data)->opline+1)->opcode == ZEND_HANDLE_EXCEPTION) {
     129             :                 /* no need to rethrow the exception */
     130        1431 :                 return;
     131             :         }
     132        3108 :         EG(opline_before_exception) = EG(current_execute_data)->opline;
     133        3108 :         EG(current_execute_data)->opline = EG(exception_op);
     134             : }
     135             : /* }}} */
     136             : 
     137         103 : ZEND_API void zend_clear_exception(void) /* {{{ */
     138             : {
     139         103 :         if (EG(prev_exception)) {
     140             : 
     141           0 :                 OBJ_RELEASE(EG(prev_exception));
     142           0 :                 EG(prev_exception) = NULL;
     143             :         }
     144         103 :         if (!EG(exception)) {
     145          91 :                 return;
     146             :         }
     147          12 :         OBJ_RELEASE(EG(exception));
     148          12 :         EG(exception) = NULL;
     149          12 :         EG(current_execute_data)->opline = EG(opline_before_exception);
     150             : #if ZEND_DEBUG
     151             :         EG(opline_before_exception) = NULL;
     152             : #endif
     153             : }
     154             : /* }}} */
     155             : 
     156        2869 : static zend_object *zend_default_exception_new_ex(zend_class_entry *class_type, int skip_top_traces) /* {{{ */
     157             : {
     158             :         zval obj;
     159             :         zend_object *object;
     160             :         zval trace;
     161             :         zend_string *filename;
     162             : 
     163        2869 :         Z_OBJ(obj) = object = zend_objects_new(class_type);
     164        2869 :         Z_OBJ_HT(obj) = &default_exception_handlers;
     165             : 
     166        2869 :         object_properties_init(object, class_type);
     167             : 
     168        2869 :         if (EG(current_execute_data)) {
     169        2837 :                 zend_fetch_debug_backtrace(&trace, skip_top_traces, 0, 0);
     170             :         } else {
     171          32 :                 array_init(&trace);
     172             :         }
     173             :         Z_SET_REFCOUNT(trace, 0);
     174             : 
     175        5681 :         if (EXPECTED(class_type != parse_exception_ce || !(filename = zend_get_compiled_filename()))) {
     176        2812 :                 zend_update_property_string(base_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename());
     177        2812 :                 zend_update_property_long(base_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno());
     178             :         } else {
     179          57 :                 zend_update_property_string(base_exception_ce, &obj, "file", sizeof("file")-1, filename->val);
     180          57 :                 zend_update_property_long(base_exception_ce, &obj, "line", sizeof("line")-1, zend_get_compiled_lineno());
     181             :         }
     182        2869 :         zend_update_property(base_exception_ce, &obj, "trace", sizeof("trace")-1, &trace);
     183             : 
     184        2869 :         return object;
     185             : }
     186             : /* }}} */
     187             : 
     188        2867 : static zend_object *zend_default_exception_new(zend_class_entry *class_type) /* {{{ */
     189             : {
     190        2867 :         return zend_default_exception_new_ex(class_type, 0);
     191             : }
     192             : /* }}} */
     193             : 
     194           2 : static zend_object *zend_error_exception_new(zend_class_entry *class_type) /* {{{ */
     195             : {
     196           2 :         return zend_default_exception_new_ex(class_type, 2);
     197             : }
     198             : /* }}} */
     199             : 
     200             : /* {{{ proto Exception Exception::__clone()
     201             :    Clone the exception object */
     202           0 : ZEND_METHOD(exception, __clone)
     203             : {
     204             :         /* Should never be executable */
     205           0 :         zend_throw_exception(NULL, "Cannot clone object using __clone()", 0);
     206           0 : }
     207             : /* }}} */
     208             : 
     209             : /* {{{ proto Exception::__construct(string message, int code [, Exception previous])
     210             :    Exception constructor */
     211         362 : ZEND_METHOD(exception, __construct)
     212             : {
     213         362 :         zend_string *message = NULL;
     214         362 :         zend_long   code = 0;
     215         362 :         zval  *object, *previous = NULL;
     216         362 :         int    argc = ZEND_NUM_ARGS();
     217             : 
     218         362 :         if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|SlO!", &message, &code, &previous, base_exception_ce) == FAILURE) {
     219           0 :                 zend_error(E_EXCEPTION | E_ERROR, "Wrong parameters for Exception([string $exception [, long $code [, Exception $previous = NULL]]])");
     220           0 :                 return;
     221             :         }
     222             : 
     223         362 :         object = getThis();
     224             : 
     225         362 :         if (message) {
     226         264 :                 zend_update_property_str(base_exception_ce, object, "message", sizeof("message")-1, message);
     227             :         }
     228             : 
     229         362 :         if (code) {
     230           6 :                 zend_update_property_long(base_exception_ce, object, "code", sizeof("code")-1, code);
     231             :         }
     232             : 
     233         362 :         if (previous) {
     234           3 :                 zend_update_property(base_exception_ce, object, "previous", sizeof("previous")-1, previous);
     235             :         }
     236             : }
     237             : /* }}} */
     238             : 
     239             : /* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Exception previous]]])
     240             :    ErrorException constructor */
     241           2 : ZEND_METHOD(error_exception, __construct)
     242             : {
     243           2 :         char  *message = NULL, *filename = NULL;
     244           2 :         zend_long   code = 0, severity = E_ERROR, lineno;
     245           2 :         zval  *object, *previous = NULL;
     246           2 :         int    argc = ZEND_NUM_ARGS();
     247             :         size_t message_len, filename_len;
     248             : 
     249           2 :         if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|sllslO!", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno, &previous, base_exception_ce) == FAILURE) {
     250           0 :                 zend_error(E_EXCEPTION | E_ERROR, "Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno  [, Exception $previous = NULL]]]]]])");
     251           0 :                 return;
     252             :         }
     253             : 
     254           2 :         object = getThis();
     255             : 
     256           2 :         if (message) {
     257           2 :                 zend_update_property_string(base_exception_ce, object, "message", sizeof("message")-1, message);
     258             :         }
     259             : 
     260           2 :         if (code) {
     261           1 :                 zend_update_property_long(base_exception_ce, object, "code", sizeof("code")-1, code);
     262             :         }
     263             : 
     264           2 :         if (previous) {
     265           0 :                 zend_update_property(base_exception_ce, object, "previous", sizeof("previous")-1, previous);
     266             :         }
     267             : 
     268           2 :         zend_update_property_long(base_exception_ce, object, "severity", sizeof("severity")-1, severity);
     269             : 
     270           2 :         if (argc >= 4) {
     271           2 :             zend_update_property_string(base_exception_ce, object, "file", sizeof("file")-1, filename);
     272           2 :         if (argc < 5) {
     273           0 :             lineno = 0; /* invalidate lineno */
     274             :         }
     275           2 :                 zend_update_property_long(base_exception_ce, object, "line", sizeof("line")-1, lineno);
     276             :         }
     277             : }
     278             : /* }}} */
     279             : 
     280             : #define DEFAULT_0_PARAMS \
     281             :         if (zend_parse_parameters_none() == FAILURE) { \
     282             :                 return; \
     283             :         }
     284             : 
     285             : #define GET_PROPERTY(object, name) \
     286             :         zend_read_property(base_exception_ce, (object), name, sizeof(name) - 1, 0, &rv)
     287             : #define GET_PROPERTY_SILENT(object, name) \
     288             :         zend_read_property(base_exception_ce, (object), name, sizeof(name) - 1, 1, &rv)
     289             : 
     290             : /* {{{ proto string Exception::getFile()
     291             :    Get the file in which the exception occurred */
     292          47 : ZEND_METHOD(exception, getFile)
     293             : {
     294             :         zval rv;
     295             : 
     296          47 :         DEFAULT_0_PARAMS;
     297             : 
     298          46 :         ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "file"));
     299             : }
     300             : /* }}} */
     301             : 
     302             : /* {{{ proto int Exception::getLine()
     303             :    Get the line in which the exception occurred */
     304          60 : ZEND_METHOD(exception, getLine)
     305             : {
     306             :         zval rv;
     307             : 
     308          60 :         DEFAULT_0_PARAMS;
     309             : 
     310          59 :         ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "line"));
     311             : }
     312             : /* }}} */
     313             : 
     314             : /* {{{ proto string Exception::getMessage()
     315             :    Get the exception message */
     316        1603 : ZEND_METHOD(exception, getMessage)
     317             : {
     318             :         zval rv;
     319             : 
     320        1603 :         DEFAULT_0_PARAMS;
     321             : 
     322        1602 :         ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "message"));
     323             : }
     324             : /* }}} */
     325             : 
     326             : /* {{{ proto int Exception::getCode()
     327             :    Get the exception code */
     328          70 : ZEND_METHOD(exception, getCode)
     329             : {
     330             :         zval rv;
     331             : 
     332          70 :         DEFAULT_0_PARAMS;
     333             : 
     334          69 :         ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "code"));
     335             : }
     336             : /* }}} */
     337             : 
     338             : /* {{{ proto array Exception::getTrace()
     339             :    Get the stack trace for the location in which the exception occurred */
     340           6 : ZEND_METHOD(exception, getTrace)
     341             : {
     342             :         zval rv;
     343             : 
     344           6 :         DEFAULT_0_PARAMS;
     345             : 
     346           5 :         ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "trace"));
     347             : }
     348             : /* }}} */
     349             : 
     350             : /* {{{ proto int ErrorException::getSeverity()
     351             :    Get the exception severity */
     352           0 : ZEND_METHOD(error_exception, getSeverity)
     353             : {
     354             :         zval rv;
     355             : 
     356           0 :         DEFAULT_0_PARAMS;
     357             : 
     358           0 :         ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "severity"));
     359             : }
     360             : /* }}} */
     361             : 
     362             : #define TRACE_APPEND_KEY(key) do {                                          \
     363             :                 tmp = zend_hash_str_find(ht, key, sizeof(key)-1);                   \
     364             :                 if (tmp) {                                                          \
     365             :                         if (Z_TYPE_P(tmp) != IS_STRING) {                               \
     366             :                                 zend_error(E_WARNING, "Value for %s is no string", key);    \
     367             :                                 smart_str_appends(str, "[unknown]");                        \
     368             :                         } else {                                                        \
     369             :                                 smart_str_append(str, Z_STR_P(tmp));   \
     370             :                         }                                                               \
     371             :                 } \
     372             :         } while (0)
     373             : 
     374             : /* Windows uses VK_ESCAPE instead of \e */
     375             : #ifndef VK_ESCAPE
     376             : #define VK_ESCAPE '\e'
     377             : #endif
     378             : 
     379         152 : static size_t compute_escaped_string_len(const char *s, size_t l) {
     380         152 :         size_t i, len = l;
     381        1505 :         for (i = 0; i < l; ++i) {
     382        1353 :                 char c = s[i];
     383        1353 :                 if (c == '\n' || c == '\r' || c == '\t' ||
     384             :                         c == '\f' || c == '\v' || c == '\\' || c == VK_ESCAPE) {
     385           0 :                         len += 1;
     386        1353 :                 } else if (c < 32 || c > 126) {
     387           5 :                         len += 3;
     388             :                 }
     389             :         }
     390         152 :         return len;
     391             : }
     392             : 
     393         152 : static void smart_str_append_escaped(smart_str *str, const char *s, size_t l) {
     394             :         char *res;
     395         152 :         size_t i, len = compute_escaped_string_len(s, l);
     396             : 
     397             :         smart_str_alloc(str, len, 0);
     398         152 :         res = &str->s->val[str->s->len];
     399         152 :         str->s->len += len;
     400             : 
     401        1505 :         for (i = 0; i < l; ++i) {
     402        1353 :                 char c = s[i];
     403        1358 :                 if (c < 32 || c == '\\' || c > 126) {
     404           5 :                         *res++ = '\\';
     405           5 :                         switch (c) {
     406           0 :                                 case '\n': *res++ = 'n'; break;
     407           0 :                                 case '\r': *res++ = 'r'; break;
     408           0 :                                 case '\t': *res++ = 't'; break;
     409           0 :                                 case '\f': *res++ = 'f'; break;
     410           0 :                                 case '\v': *res++ = 'v'; break;
     411           0 :                                 case '\\': *res++ = '\\'; break;
     412           0 :                                 case VK_ESCAPE: *res++ = 'e'; break;
     413             :                                 default:
     414           5 :                                         *res++ = 'x';
     415           5 :                                         if ((c >> 4) < 10) {
     416           5 :                                                 *res++ = (c >> 4) + '0';
     417             :                                         } else {
     418           0 :                                                 *res++ = (c >> 4) + 'A' - 10;
     419             :                                         }
     420           5 :                                         if ((c & 0xf) < 10) {
     421           5 :                                                 *res++ = (c & 0xf) + '0';
     422             :                                         } else {
     423           0 :                                                 *res++ = (c & 0xf) + 'A' - 10;
     424             :                                         }
     425             :                         }
     426             :                 } else {
     427        1348 :                         *res++ = c;
     428             :                 }
     429             :         }
     430         152 : }
     431             : 
     432         344 : static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */
     433             : {
     434             :         /* the trivial way would be to do
     435             :          * convert_to_string_ex(arg);
     436             :          * append it and kill the now tmp arg.
     437             :          * but that could cause some E_NOTICE and also damn long lines.
     438             :          */
     439             : 
     440         344 :         ZVAL_DEREF(arg);
     441         344 :         switch (Z_TYPE_P(arg)) {
     442             :                 case IS_NULL:
     443             :                         smart_str_appends(str, "NULL, ");
     444          13 :                         break;
     445             :                 case IS_STRING:
     446             :                         smart_str_appendc(str, '\'');
     447         152 :                         smart_str_append_escaped(str, Z_STRVAL_P(arg), MIN(Z_STRLEN_P(arg), 15));
     448         152 :                         if (Z_STRLEN_P(arg) > 15) {
     449             :                                 smart_str_appends(str, "...', ");
     450             :                         } else {
     451             :                                 smart_str_appends(str, "', ");
     452             :                         }
     453         152 :                         break;
     454             :                 case IS_FALSE:
     455             :                         smart_str_appends(str, "false, ");
     456           9 :                         break;
     457             :                 case IS_TRUE:
     458             :                         smart_str_appends(str, "true, ");
     459           1 :                         break;
     460             :                 case IS_RESOURCE:
     461             :                         smart_str_appends(str, "Resource id #");
     462           1 :                         smart_str_append_long(str, Z_RES_HANDLE_P(arg));
     463             :                         smart_str_appends(str, ", ");
     464           1 :                         break;
     465             :                 case IS_LONG:
     466          82 :                         smart_str_append_long(str, Z_LVAL_P(arg));
     467             :                         smart_str_appends(str, ", ");
     468          82 :                         break;
     469             :                 case IS_DOUBLE: {
     470           1 :                         double dval = Z_DVAL_P(arg);
     471           1 :                         char *s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
     472           1 :                         int l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval);  /* SAFE */
     473           1 :                         smart_str_appendl(str, s_tmp, l_tmp);
     474             :                         smart_str_appends(str, ", ");
     475           1 :                         efree(s_tmp);
     476           1 :                         break;
     477             :                 }
     478             :                 case IS_ARRAY:
     479             :                         smart_str_appends(str, "Array, ");
     480          48 :                         break;
     481             :                 case IS_OBJECT:
     482             :                         smart_str_appends(str, "Object(");
     483          37 :                         smart_str_append(str, Z_OBJCE_P(arg)->name);
     484             :                         smart_str_appends(str, "), ");
     485             :                         break;
     486             :         }
     487         344 : }
     488             : /* }}} */
     489             : 
     490         379 : static void _build_trace_string(smart_str *str, HashTable *ht, uint32_t num) /* {{{ */
     491             : {
     492             :         zval *file, *tmp;
     493             : 
     494             :         smart_str_appendc(str, '#');
     495         379 :         smart_str_append_long(str, num);
     496             :         smart_str_appendc(str, ' ');
     497             : 
     498         379 :         file = zend_hash_str_find(ht, "file", sizeof("file")-1);
     499         379 :         if (file) {
     500         316 :                 if (Z_TYPE_P(file) != IS_STRING) {
     501           1 :                         zend_error(E_WARNING, "Function name is no string");
     502             :                         smart_str_appends(str, "[unknown function]");
     503             :                 } else{
     504             :                         zend_long line;
     505         315 :                         tmp = zend_hash_str_find(ht, "line", sizeof("line")-1);
     506         315 :                         if (tmp) {
     507         315 :                                 if (Z_TYPE_P(tmp) == IS_LONG) {
     508         315 :                                         line = Z_LVAL_P(tmp);
     509             :                                 } else {
     510           0 :                                         zend_error(E_WARNING, "Line is no long");
     511           0 :                                         line = 0;
     512             :                                 }
     513             :                         } else {
     514           0 :                                 line = 0;
     515             :                         }
     516         315 :                         smart_str_append(str, Z_STR_P(file));
     517             :                         smart_str_appendc(str, '(');
     518             :                         smart_str_append_long(str, line);
     519             :                         smart_str_appends(str, "): ");
     520             :                 }
     521             :         } else {
     522             :                 smart_str_appends(str, "[internal function]: ");
     523             :         }
     524         760 :         TRACE_APPEND_KEY("class");
     525         760 :         TRACE_APPEND_KEY("type");
     526        1134 :         TRACE_APPEND_KEY("function");
     527             :         smart_str_appendc(str, '(');
     528         379 :         tmp = zend_hash_str_find(ht, "args", sizeof("args")-1);
     529         379 :         if (tmp) {
     530         374 :                 if (Z_TYPE_P(tmp) == IS_ARRAY) {
     531         373 :                         size_t last_len = str->s->len;
     532             :                         zval *arg;
     533             : 
     534        1103 :                         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(tmp), arg) {
     535         344 :                                 _build_trace_args(arg, str);
     536             :                         } ZEND_HASH_FOREACH_END();
     537             : 
     538         373 :                         if (last_len != str->s->len) {
     539         196 :                                 str->s->len -= 2; /* remove last ', ' */
     540             :                         }
     541             :                 } else {
     542           1 :                         zend_error(E_WARNING, "args element is no array");
     543             :                 }
     544             :         }
     545             :         smart_str_appends(str, ")\n");
     546         379 : }
     547             : /* }}} */
     548             : 
     549             : /* {{{ proto string Exception::getTraceAsString()
     550             :    Obtain the backtrace for the exception as a string (instead of an array) */
     551         508 : ZEND_METHOD(exception, getTraceAsString)
     552             : {
     553             :         zval *trace, *frame, rv;
     554             :         zend_ulong index;
     555         508 :         smart_str str = {0};
     556         508 :         uint32_t num = 0;
     557             : 
     558         508 :         DEFAULT_0_PARAMS;
     559             : 
     560         507 :         trace = zend_read_property(base_exception_ce, getThis(), "trace", sizeof("trace")-1, 1, &rv);
     561         507 :         if (Z_TYPE_P(trace) != IS_ARRAY) {
     562           1 :                 RETURN_FALSE;
     563             :         }
     564        1266 :         ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(trace), index, frame) {
     565         380 :                 if (Z_TYPE_P(frame) != IS_ARRAY) {
     566           1 :                         zend_error(E_WARNING, "Expected array for frame %pu", index);
     567           1 :                         continue;
     568             :                 }
     569             : 
     570         379 :                 _build_trace_string(&str, Z_ARRVAL_P(frame), num++);
     571             :         } ZEND_HASH_FOREACH_END();
     572             : 
     573             :         smart_str_appendc(&str, '#');
     574         506 :         smart_str_append_long(&str, num);
     575             :         smart_str_appends(&str, " {main}");
     576             :         smart_str_0(&str);
     577             : 
     578         506 :         RETURN_NEW_STR(str.s);
     579             : }
     580             : /* }}} */
     581             : 
     582             : /* {{{ proto string Exception::getPrevious()
     583             :    Return previous Exception or NULL. */
     584          11 : ZEND_METHOD(exception, getPrevious)
     585             : {
     586             :         zval rv;
     587             : 
     588          11 :         DEFAULT_0_PARAMS;
     589             : 
     590          11 :         ZVAL_COPY(return_value, GET_PROPERTY_SILENT(getThis(), "previous"));
     591             : } /* }}} */
     592             : 
     593        2865 : size_t zend_spprintf(char **message, size_t max_len, const char *format, ...) /* {{{ */
     594             : {
     595             :         va_list arg;
     596             :         size_t len;
     597             : 
     598        2865 :         va_start(arg, format);
     599        2865 :         len = zend_vspprintf(message, max_len, format, arg);
     600        2865 :         va_end(arg);
     601        2865 :         return len;
     602             : }
     603             : /* }}} */
     604             : 
     605        8423 : zend_string *zend_strpprintf(size_t max_len, const char *format, ...) /* {{{ */
     606             : {
     607             :         va_list arg;
     608             :         zend_string *str;
     609             : 
     610        8423 :         va_start(arg, format);
     611        8423 :         str = zend_vstrpprintf(max_len, format, arg);
     612        8423 :         va_end(arg);
     613        8423 :         return str;
     614             : }
     615             : /* }}} */
     616             : 
     617             : /* {{{ proto string Exception::__toString()
     618             :    Obtain the string representation of the Exception object */
     619         493 : ZEND_METHOD(exception, __toString)
     620             : {
     621             :         zval trace, *exception;
     622             :         zend_string *str;
     623             :         zend_fcall_info fci;
     624             :         zval fname, rv;
     625             : 
     626         493 :         DEFAULT_0_PARAMS;
     627             : 
     628         492 :         str = STR_EMPTY_ALLOC();
     629             : 
     630         492 :         exception = getThis();
     631         984 :         ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1);
     632             : 
     633        2478 :         while (exception && Z_TYPE_P(exception) == IS_OBJECT) {
     634         502 :                 zend_string *prev_str = str;
     635        1003 :                 zend_string *message = zval_get_string(GET_PROPERTY(exception, "message"));
     636        1002 :                 zend_string *file = zval_get_string(GET_PROPERTY(exception, "file"));
     637        1002 :                 zend_long line = zval_get_long(GET_PROPERTY(exception, "line"));
     638             : 
     639         501 :                 fci.size = sizeof(fci);
     640         501 :                 fci.function_table = &Z_OBJCE_P(exception)->function_table;
     641         501 :                 ZVAL_COPY_VALUE(&fci.function_name, &fname);
     642         501 :                 fci.symbol_table = NULL;
     643         501 :                 fci.object = Z_OBJ_P(exception);
     644         501 :                 fci.retval = &trace;
     645         501 :                 fci.param_count = 0;
     646         501 :                 fci.params = NULL;
     647         501 :                 fci.no_separation = 1;
     648             : 
     649         501 :                 zend_call_function(&fci, NULL);
     650             : 
     651         501 :                 if (Z_TYPE(trace) != IS_STRING) {
     652           1 :                         zval_ptr_dtor(&trace);
     653           1 :                         ZVAL_UNDEF(&trace);
     654             :                 }
     655             : 
     656         501 :                 if (Z_OBJCE_P(exception) == type_exception_ce && strstr(message->val, ", called in ")) {
     657          24 :                         zend_string *real_message = zend_strpprintf(0, "%s and defined", message->val);
     658             :                         zend_string_release(message);
     659          24 :                         message = real_message;
     660             :                 }
     661             : 
     662         501 :                 if (message->len > 0) {
     663        2832 :                         str = zend_strpprintf(0, "%s: %s in %s:" ZEND_LONG_FMT
     664             :                                         "\nStack trace:\n%s%s%s",
     665         472 :                                         Z_OBJCE_P(exception)->name->val, message->val, file->val, line,
     666         944 :                                         (Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
     667         472 :                                         prev_str->len ? "\n\nNext " : "", prev_str->val);
     668             :                 } else {
     669         172 :                         str = zend_strpprintf(0, "%s in %s:" ZEND_LONG_FMT
     670             :                                         "\nStack trace:\n%s%s%s",
     671          29 :                                         Z_OBJCE_P(exception)->name->val, file->val, line,
     672          56 :                                         (Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
     673          29 :                                         prev_str->len ? "\n\nNext " : "", prev_str->val);
     674             :                 }
     675             : 
     676             :                 zend_string_release(prev_str);
     677             :                 zend_string_release(message);
     678             :                 zend_string_release(file);
     679         501 :                 zval_ptr_dtor(&trace);
     680             : 
     681         501 :                 exception = GET_PROPERTY(exception, "previous");
     682             :         }
     683             :         zval_dtor(&fname);
     684             : 
     685             :         /* We store the result in the private property string so we can access
     686             :          * the result in uncaught exception handlers without memleaks. */
     687         491 :         zend_update_property_str(base_exception_ce, getThis(), "string", sizeof("string")-1, str);
     688             : 
     689         491 :         RETURN_STR(str);
     690             : }
     691             : /* }}} */
     692             : 
     693             : /* {{{ internal structs */
     694             : /* All functions that may be used in uncaught exception handlers must be final
     695             :  * and must not throw exceptions. Otherwise we would need a facility to handle
     696             :  * such exceptions in that handler.
     697             :  * Also all getXY() methods are final because thy serve as read only access to
     698             :  * their corresponding properties, no more, no less. If after all you need to
     699             :  * override somthing then it is method __toString().
     700             :  * And never try to change the state of exceptions and never implement anything
     701             :  * that gives the user anything to accomplish this.
     702             :  */
     703             : ZEND_BEGIN_ARG_INFO_EX(arginfo_exception___construct, 0, 0, 0)
     704             :         ZEND_ARG_INFO(0, message)
     705             :         ZEND_ARG_INFO(0, code)
     706             :         ZEND_ARG_INFO(0, previous)
     707             : ZEND_END_ARG_INFO()
     708             : 
     709             : static const zend_function_entry default_exception_functions[] = {
     710             :         ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
     711             :         ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC)
     712             :         ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     713             :         ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     714             :         ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     715             :         ZEND_ME(exception, getLine, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     716             :         ZEND_ME(exception, getTrace, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     717             :         ZEND_ME(exception, getPrevious, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     718             :         ZEND_ME(exception, getTraceAsString, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     719             :         ZEND_ME(exception, __toString, NULL, 0)
     720             :         ZEND_FE_END
     721             : };
     722             : 
     723             : ZEND_BEGIN_ARG_INFO_EX(arginfo_error_exception___construct, 0, 0, 0)
     724             :         ZEND_ARG_INFO(0, message)
     725             :         ZEND_ARG_INFO(0, code)
     726             :         ZEND_ARG_INFO(0, severity)
     727             :         ZEND_ARG_INFO(0, filename)
     728             :         ZEND_ARG_INFO(0, lineno)
     729             :         ZEND_ARG_INFO(0, previous)
     730             : ZEND_END_ARG_INFO()
     731             : 
     732             : static const zend_function_entry error_exception_functions[] = {
     733             :         ZEND_ME(error_exception, __construct, arginfo_error_exception___construct, ZEND_ACC_PUBLIC)
     734             :         ZEND_ME(error_exception, getSeverity, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
     735             :         ZEND_FE_END
     736             : };
     737             : /* }}} */
     738             : 
     739       20916 : void zend_register_default_exception(void) /* {{{ */
     740             : {
     741             :         zend_class_entry ce;
     742             :         zend_property_info *prop;
     743             : 
     744       20916 :         INIT_CLASS_ENTRY(ce, "BaseException", default_exception_functions);
     745       20916 :         base_exception_ce = zend_register_internal_class(&ce);
     746       20916 :         base_exception_ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
     747       20916 :         base_exception_ce->create_object = NULL;
     748       20916 :         memcpy(&default_exception_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
     749       20916 :         default_exception_handlers.clone_obj = NULL;
     750             : 
     751       20916 :         zend_declare_property_string(base_exception_ce, "message", sizeof("message")-1, "", ZEND_ACC_PROTECTED);
     752       20916 :         zend_declare_property_string(base_exception_ce, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE);
     753       20916 :         zend_declare_property_long(base_exception_ce, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED);
     754       20916 :         zend_declare_property_null(base_exception_ce, "file", sizeof("file")-1, ZEND_ACC_PROTECTED);
     755       20916 :         zend_declare_property_null(base_exception_ce, "line", sizeof("line")-1, ZEND_ACC_PROTECTED);
     756       20916 :         zend_declare_property_null(base_exception_ce, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE);
     757       20916 :         zend_declare_property_null(base_exception_ce, "previous", sizeof("previous")-1, ZEND_ACC_PRIVATE);
     758             : 
     759       20916 :         INIT_CLASS_ENTRY(ce, "Exception", NULL);
     760       20916 :         default_exception_ce = zend_register_internal_class_ex(&ce, base_exception_ce);
     761       20916 :         default_exception_ce->create_object = zend_default_exception_new;
     762             : 
     763             :         /* A trick, to make visible private properties of BaseException */
     764      313740 :         ZEND_HASH_FOREACH_PTR(&default_exception_ce->properties_info, prop) {
     765      146412 :                 if (prop->flags & ZEND_ACC_SHADOW) {
     766       62748 :                         if (prop->name->len == sizeof("\0BaseException\0string")-1) {
     767       20916 :                                 prop->flags &= ~ZEND_ACC_SHADOW;
     768       20916 :                                 prop->flags |= ZEND_ACC_PRIVATE;
     769       20916 :                                 prop->ce = default_exception_ce;
     770       41832 :                         } else if (prop->name->len == sizeof("\0BaseException\0trace")-1) {
     771       20916 :                                 prop->flags &= ~ZEND_ACC_SHADOW;
     772       20916 :                                 prop->flags |= ZEND_ACC_PRIVATE;
     773       20916 :                                 prop->ce = default_exception_ce;
     774       20916 :                         } else if (prop->name->len == sizeof("\0BaseException\0previous")-1) {
     775       20916 :                                 prop->flags &= ~ZEND_ACC_SHADOW;
     776       20916 :                                 prop->flags |= ZEND_ACC_PRIVATE;
     777       20916 :                                 prop->ce = default_exception_ce;
     778             :                         }
     779             :                 }
     780             :         } ZEND_HASH_FOREACH_END();
     781             : 
     782       20916 :         INIT_CLASS_ENTRY(ce, "ErrorException", error_exception_functions);
     783       20916 :         error_exception_ce = zend_register_internal_class_ex(&ce, default_exception_ce);
     784       20916 :         error_exception_ce->create_object = zend_error_exception_new;
     785       20916 :         zend_declare_property_long(error_exception_ce, "severity", sizeof("severity")-1, E_ERROR, ZEND_ACC_PROTECTED);
     786             : 
     787       20916 :         INIT_CLASS_ENTRY(ce, "EngineException", NULL);
     788       20916 :         engine_exception_ce = zend_register_internal_class_ex(&ce, base_exception_ce);
     789       20916 :         engine_exception_ce->create_object = zend_default_exception_new;
     790             : 
     791       20916 :         INIT_CLASS_ENTRY(ce, "ParseException", NULL);
     792       20916 :         parse_exception_ce = zend_register_internal_class_ex(&ce, base_exception_ce);
     793       20916 :         parse_exception_ce->create_object = zend_default_exception_new;
     794             : 
     795       20916 :         INIT_CLASS_ENTRY(ce, "TypeException", NULL);
     796       20916 :         type_exception_ce = zend_register_internal_class_ex(&ce, engine_exception_ce);
     797       20916 :         type_exception_ce->create_object = zend_default_exception_new;
     798       20916 : }
     799             : /* }}} */
     800             : 
     801           2 : ZEND_API zend_class_entry *zend_exception_get_base(void) /* {{{ */
     802             : {
     803           2 :         return base_exception_ce;
     804             : }
     805             : /* }}} */
     806             : 
     807      188734 : ZEND_API zend_class_entry *zend_exception_get_default(void) /* {{{ */
     808             : {
     809      188734 :         return default_exception_ce;
     810             : }
     811             : /* }}} */
     812             : 
     813           0 : ZEND_API zend_class_entry *zend_get_error_exception(void) /* {{{ */
     814             : {
     815           0 :         return error_exception_ce;
     816             : }
     817             : /* }}} */
     818             : 
     819         296 : ZEND_API zend_class_entry *zend_get_engine_exception(void) /* {{{ */
     820             : {
     821         296 :         return engine_exception_ce;
     822             : }
     823             : /* }}} */
     824             : 
     825          57 : ZEND_API zend_class_entry *zend_get_parse_exception(void) /* {{{ */
     826             : {
     827          57 :         return parse_exception_ce;
     828             : }
     829             : /* }}} */
     830             : 
     831         491 : ZEND_API zend_class_entry *zend_get_type_exception(void) /* {{{ */
     832             : {
     833         491 :         return type_exception_ce;
     834             : }
     835             : /* }}} */
     836             : 
     837             : 
     838        2012 : ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code) /* {{{ */
     839             : {
     840             :         zval ex;
     841             : 
     842        2012 :         if (exception_ce) {
     843        1623 :                 if (!instanceof_function(exception_ce, base_exception_ce)) {
     844           0 :                         zend_error(E_NOTICE, "Exceptions must be derived from the Exception base class");
     845           0 :                         exception_ce = default_exception_ce;
     846             :                 }
     847             :         } else {
     848         389 :                 exception_ce = default_exception_ce;
     849             :         }
     850        2012 :         object_init_ex(&ex, exception_ce);
     851             : 
     852             : 
     853        2012 :         if (message) {
     854        2012 :                 zend_update_property_string(base_exception_ce, &ex, "message", sizeof("message")-1, message);
     855             :         }
     856        2012 :         if (code) {
     857         933 :                 zend_update_property_long(base_exception_ce, &ex, "code", sizeof("code")-1, code);
     858             :         }
     859             : 
     860        2012 :         zend_throw_exception_internal(&ex);
     861        2012 :         return Z_OBJ(ex);
     862             : }
     863             : /* }}} */
     864             : 
     865         901 : ZEND_API zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code, const char *format, ...) /* {{{ */
     866             : {
     867             :         va_list arg;
     868             :         char *message;
     869             :         zend_object *obj;
     870             : 
     871         901 :         va_start(arg, format);
     872         901 :         zend_vspprintf(&message, 0, format, arg);
     873         901 :         va_end(arg);
     874         901 :         obj = zend_throw_exception(exception_ce, message, code);
     875         901 :         efree(message);
     876         901 :         return obj;
     877             : }
     878             : /* }}} */
     879             : 
     880          82 : ZEND_API zend_object *zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, zend_long code, int severity) /* {{{ */
     881             : {
     882             :         zval ex;
     883          82 :         zend_object *obj = zend_throw_exception(exception_ce, message, code);
     884          82 :         ZVAL_OBJ(&ex, obj);
     885          82 :         zend_update_property_long(base_exception_ce, &ex, "severity", sizeof("severity")-1, severity);
     886          82 :         return obj;
     887             : }
     888             : /* }}} */
     889             : 
     890         451 : static void zend_error_va(int type, const char *file, uint lineno, const char *format, ...) /* {{{ */
     891             : {
     892             :         va_list args;
     893             : 
     894         451 :         va_start(args, format);
     895         451 :         zend_error_cb(type, file, lineno, format, args);
     896           3 :         va_end(args);
     897           3 : }
     898             : /* }}} */
     899             : 
     900          45 : static void zend_error_helper(int type, const char *filename, const uint lineno, const char *format, ...)
     901             : {
     902             :         va_list va;
     903             : 
     904          45 :         va_start(va, format);
     905          45 :         zend_error_cb(type, filename, lineno, format, va);
     906          44 :         va_end(va);
     907          44 : }
     908             : 
     909             : /* This function doesn't return if it uses E_ERROR */
     910         497 : ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */
     911             : {
     912             :         zval exception, rv;
     913             :         zend_class_entry *ce_exception;
     914             : 
     915         497 :         ZVAL_OBJ(&exception, ex);
     916         497 :         ce_exception = Z_OBJCE(exception);
     917         497 :         EG(exception) = NULL;
     918         497 :         if (ce_exception == parse_exception_ce) {
     919          90 :                 zend_string *message = zval_get_string(GET_PROPERTY(&exception, "message"));
     920          90 :                 zend_string *file = zval_get_string(GET_PROPERTY_SILENT(&exception, "file"));
     921          90 :                 zend_long line = zval_get_long(GET_PROPERTY_SILENT(&exception, "line"));
     922          90 :                 zend_long code = zval_get_long(GET_PROPERTY_SILENT(&exception, "code"));
     923             : 
     924          45 :                 zend_error_helper(code? code : E_ERROR, file->val, line, "%s", message->val);
     925             : 
     926             :                 zend_string_release(file);
     927             :                 zend_string_release(message);
     928         452 :         } else if (instanceof_function(ce_exception, base_exception_ce)) {
     929             :                 zval tmp, rv;
     930         452 :                 zend_string *str, *file = NULL;
     931         452 :                 zend_long line = 0;
     932             : 
     933         452 :                 zend_call_method_with_0_params(&exception, ce_exception, NULL, "__tostring", &tmp);
     934         451 :                 if (!EG(exception)) {
     935         451 :                         if (Z_TYPE(tmp) != IS_STRING) {
     936           0 :                                 zend_error(E_WARNING, "%s::__toString() must return a string", ce_exception->name->val);
     937             :                         } else {
     938         451 :                                 zend_update_property_string(base_exception_ce, &exception, "string", sizeof("string")-1, EG(exception) ? ce_exception->name->val : Z_STRVAL(tmp));
     939             :                         }
     940             :                 }
     941         451 :                 zval_ptr_dtor(&tmp);
     942             : 
     943         451 :                 if (EG(exception)) {
     944             :                         zval zv;
     945             : 
     946           0 :                         ZVAL_OBJ(&zv, EG(exception));
     947             :                         /* do the best we can to inform about the inner exception */
     948           0 :                         if (instanceof_function(ce_exception, base_exception_ce)) {
     949           0 :                                 file = zval_get_string(GET_PROPERTY_SILENT(&zv, "file"));
     950           0 :                                 line = zval_get_long(GET_PROPERTY_SILENT(&zv, "line"));
     951             :                         }
     952             : 
     953           0 :                         zend_error_va(E_WARNING, (file && file->len > 0) ? file->val : NULL, line,
     954             :                                 "Uncaught %s in exception handling during call to %s::__tostring()",
     955           0 :                                 Z_OBJCE(zv)->name->val, ce_exception->name->val);
     956             : 
     957           0 :                         if (file) {
     958             :                                 zend_string_release(file);
     959             :                         }
     960             :                 }
     961             : 
     962         902 :                 str = zval_get_string(GET_PROPERTY_SILENT(&exception, "string"));
     963         902 :                 file = zval_get_string(GET_PROPERTY_SILENT(&exception, "file"));
     964         902 :                 line = zval_get_long(GET_PROPERTY_SILENT(&exception, "line"));
     965             : 
     966         451 :                 zend_error_va(severity, (file && file->len > 0) ? file->val : NULL, line,
     967             :                         "Uncaught %s\n  thrown", str->val);
     968             : 
     969             :                 zend_string_release(str);
     970             :                 zend_string_release(file);
     971             :         } else {
     972           0 :                 zend_error(severity, "Uncaught exception '%s'", ce_exception->name->val);
     973             :         }
     974             : 
     975             :         OBJ_RELEASE(ex);
     976          47 : }
     977             : /* }}} */
     978             : 
     979         438 : ZEND_API void zend_throw_exception_object(zval *exception) /* {{{ */
     980             : {
     981             :         zend_class_entry *exception_ce;
     982             : 
     983         876 :         if (exception == NULL || Z_TYPE_P(exception) != IS_OBJECT) {
     984           0 :                 zend_error_noreturn(E_CORE_ERROR, "Need to supply an object when throwing an exception");
     985             :         }
     986             : 
     987         438 :         exception_ce = Z_OBJCE_P(exception);
     988             : 
     989         438 :         if (!exception_ce || !instanceof_function(exception_ce, base_exception_ce)) {
     990           2 :                 zend_error(E_EXCEPTION | E_ERROR, "Exceptions must be valid objects derived from the Exception base class");
     991           2 :                 return;
     992             :         }
     993         436 :         zend_throw_exception_internal(exception);
     994             : }
     995             : /* }}} */
     996             : 
     997             : /*
     998             :  * Local variables:
     999             :  * tab-width: 4
    1000             :  * c-basic-offset: 4
    1001             :  * indent-tabs-mode: t
    1002             :  * End:
    1003             :  */

Generated by: LCOV version 1.10

Generated at Thu, 21 May 2015 19:58:51 +0000 (14 hours ago)

Copyright © 2005-2015 The PHP Group
All rights reserved.