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

Generated by: LCOV version 1.10

Generated at Sun, 18 Sep 2016 08:20:01 +0000 (8 days ago)

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