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

Generated by: LCOV version 1.10

Generated at Wed, 31 Aug 2016 04:10:59 +0000 (21 hours ago)

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