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: 377 411 91.7 %
Date: 2016-04-27 Functions: 34 38 89.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Wed, 27 Apr 2016 15:51:35 +0000 (4 days ago)

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