diff options
Diffstat (limited to 'Zend/zend_exceptions.c')
-rw-r--r-- | Zend/zend_exceptions.c | 318 |
1 files changed, 161 insertions, 157 deletions
diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index df61fb741f..4a85e4e73a 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2015 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -58,42 +58,54 @@ static int zend_implement_throwable(zend_class_entry *interface, zend_class_entr } /* }}} */ -static inline zend_class_entry *i_get_exception_base(zval *object) +static inline zend_class_entry *i_get_exception_base(zval *object) /* {{{ */ { return instanceof_function(Z_OBJCE_P(object), zend_ce_exception) ? zend_ce_exception : zend_ce_error; } +/* }}} */ -ZEND_API zend_class_entry *zend_get_exception_base(zval *object) +ZEND_API zend_class_entry *zend_get_exception_base(zval *object) /* {{{ */ { return i_get_exception_base(object); } +/* }}} */ -void zend_exception_set_previous(zend_object *exception, zend_object *add_previous) +void zend_exception_set_previous(zend_object *exception, zend_object *add_previous) /* {{{ */ { - zval tmp, *previous, zv, *pzv, rv; + zval *previous, *ancestor, *ex; + zval pv, zv, rv; zend_class_entry *base_ce; if (exception == add_previous || !add_previous || !exception) { return; } - ZVAL_OBJ(&tmp, add_previous); - if (!instanceof_function(Z_OBJCE(tmp), zend_ce_throwable)) { + ZVAL_OBJ(&pv, add_previous); + if (!instanceof_function(Z_OBJCE(pv), zend_ce_throwable)) { zend_error_noreturn(E_CORE_ERROR, "Previous exception must implement Throwable"); return; } ZVAL_OBJ(&zv, exception); - pzv = &zv; + ex = &zv; do { - base_ce = i_get_exception_base(pzv); - previous = zend_read_property(base_ce, pzv, "previous", sizeof("previous")-1, 1, &rv); + ancestor = zend_read_property_ex(i_get_exception_base(&pv), &pv, CG(known_strings)[ZEND_STR_PREVIOUS], 1, &rv); + while (Z_TYPE_P(ancestor) == IS_OBJECT) { + if (Z_OBJ_P(ancestor) == Z_OBJ_P(ex)) { + OBJ_RELEASE(add_previous); + return; + } + ancestor = zend_read_property_ex(i_get_exception_base(ancestor), ancestor, CG(known_strings)[ZEND_STR_PREVIOUS], 1, &rv); + } + base_ce = i_get_exception_base(ex); + previous = zend_read_property_ex(base_ce, ex, CG(known_strings)[ZEND_STR_PREVIOUS], 1, &rv); if (Z_TYPE_P(previous) == IS_NULL) { - zend_update_property(base_ce, pzv, "previous", sizeof("previous")-1, &tmp); + zend_update_property_ex(base_ce, ex, CG(known_strings)[ZEND_STR_PREVIOUS], &pv); GC_REFCOUNT(add_previous)--; return; } - pzv = previous; - } while (pzv && Z_OBJ_P(pzv) != add_previous); + ex = previous; + } while (Z_OBJ_P(ex) != add_previous); } +/* }}} */ void zend_exception_save(void) /* {{{ */ { @@ -120,7 +132,7 @@ void zend_exception_restore(void) /* {{{ */ } /* }}} */ -ZEND_API void zend_throw_exception_internal(zval *exception) /* {{{ */ +ZEND_API ZEND_COLD void zend_throw_exception_internal(zval *exception) /* {{{ */ { #ifdef HAVE_DTRACE if (DTRACE_EXCEPTION_THROWN_ENABLED()) { @@ -186,7 +198,7 @@ ZEND_API void zend_clear_exception(void) /* {{{ */ static zend_object *zend_default_exception_new_ex(zend_class_entry *class_type, int skip_top_traces) /* {{{ */ { - zval obj; + zval obj, tmp; zend_object *object; zval trace; zend_class_entry *base_ce; @@ -203,17 +215,22 @@ static zend_object *zend_default_exception_new_ex(zend_class_entry *class_type, array_init(&trace); } Z_SET_REFCOUNT(trace, 0); - + base_ce = i_get_exception_base(&obj); if (EXPECTED(class_type != zend_ce_parse_error || !(filename = zend_get_compiled_filename()))) { - zend_update_property_string(base_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename()); - zend_update_property_long(base_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno()); + ZVAL_STRING(&tmp, zend_get_executed_filename()); + zend_update_property_ex(base_ce, &obj, CG(known_strings)[ZEND_STR_FILE], &tmp); + zval_ptr_dtor(&tmp); + ZVAL_LONG(&tmp, zend_get_executed_lineno()); + zend_update_property_ex(base_ce, &obj, CG(known_strings)[ZEND_STR_LINE], &tmp); } else { - zend_update_property_string(base_ce, &obj, "file", sizeof("file")-1, ZSTR_VAL(filename)); - zend_update_property_long(base_ce, &obj, "line", sizeof("line")-1, zend_get_compiled_lineno()); + ZVAL_STR(&tmp, filename); + zend_update_property_ex(base_ce, &obj, CG(known_strings)[ZEND_STR_FILE], &tmp); + ZVAL_LONG(&tmp, zend_get_compiled_lineno()); + zend_update_property_ex(base_ce, &obj, CG(known_strings)[ZEND_STR_LINE], &tmp); } - zend_update_property(base_ce, &obj, "trace", sizeof("trace")-1, &trace); + zend_update_property_ex(base_ce, &obj, CG(known_strings)[ZEND_STR_TRACE], &trace); return object; } @@ -233,7 +250,7 @@ static zend_object *zend_error_exception_new(zend_class_entry *class_type) /* {{ /* {{{ proto Exception|Error Exception|Error::__clone() Clone the exception object */ -ZEND_METHOD(exception, __clone) +ZEND_COLD ZEND_METHOD(exception, __clone) { /* Should never be executable */ zend_throw_exception(NULL, "Cannot clone object using __clone()", 0); @@ -246,7 +263,7 @@ ZEND_METHOD(exception, __construct) { zend_string *message = NULL; zend_long code = 0; - zval *object, *previous = NULL; + zval tmp, *object, *previous = NULL; zend_class_entry *base_ce; int argc = ZEND_NUM_ARGS(); @@ -256,26 +273,56 @@ ZEND_METHOD(exception, __construct) if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|SlO!", &message, &code, &previous, zend_ce_throwable) == FAILURE) { zend_class_entry *ce; - if (execute_data->called_scope) { - ce = execute_data->called_scope; + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else if (Z_CE(EX(This))) { + ce = Z_CE(EX(This)); } else { ce = base_ce; } - zend_throw_error(zend_ce_error, "Wrong parameters for %s([string $message [, long $code [, Throwable $previous = NULL]]])", ZSTR_VAL(ce->name)); + zend_throw_error(NULL, "Wrong parameters for %s([string $message [, long $code [, Throwable $previous = NULL]]])", ZSTR_VAL(ce->name)); return; } if (message) { - zend_update_property_str(base_ce, object, "message", sizeof("message")-1, message); + ZVAL_STR(&tmp, message); + zend_update_property_ex(base_ce, object, CG(known_strings)[ZEND_STR_MESSAGE], &tmp); } if (code) { - zend_update_property_long(base_ce, object, "code", sizeof("code")-1, code); + ZVAL_LONG(&tmp, code); + zend_update_property_ex(base_ce, object, CG(known_strings)[ZEND_STR_CODE], &tmp); } if (previous) { - zend_update_property(base_ce, object, "previous", sizeof("previous")-1, previous); + zend_update_property_ex(base_ce, object, CG(known_strings)[ZEND_STR_PREVIOUS], previous); + } +} +/* }}} */ + +/* {{{ proto Exception::__wakeup() + Exception unserialize checks */ +#define CHECK_EXC_TYPE(id, type) \ + ZVAL_UNDEF(&value); \ + pvalue = zend_read_property_ex(i_get_exception_base(object), (object), CG(known_strings)[id], 1, &value); \ + if(Z_TYPE_P(pvalue) != IS_UNDEF && Z_TYPE_P(pvalue) != type) { \ + zval tmp; \ + ZVAL_STR_COPY(&tmp, CG(known_strings)[id]); \ + Z_OBJ_HANDLER_P(object, unset_property)(object, &tmp, NULL); \ + zval_ptr_dtor(&tmp); \ } + +ZEND_METHOD(exception, __wakeup) +{ + zval value, *pvalue; + zval *object = getThis(); + CHECK_EXC_TYPE(ZEND_STR_MESSAGE, IS_STRING); + CHECK_EXC_TYPE(ZEND_STR_STRING, IS_STRING); + CHECK_EXC_TYPE(ZEND_STR_CODE, IS_LONG); + CHECK_EXC_TYPE(ZEND_STR_FILE, IS_STRING); + CHECK_EXC_TYPE(ZEND_STR_LINE, IS_LONG); + CHECK_EXC_TYPE(ZEND_STR_TRACE, IS_ARRAY); + CHECK_EXC_TYPE(ZEND_STR_PREVIOUS, IS_OBJECT); } /* }}} */ @@ -285,44 +332,53 @@ ZEND_METHOD(error_exception, __construct) { char *message = NULL, *filename = NULL; zend_long code = 0, severity = E_ERROR, lineno; - zval *object, *previous = NULL; + zval tmp, *object, *previous = NULL; int argc = ZEND_NUM_ARGS(); size_t message_len, filename_len; 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) { zend_class_entry *ce; - if (execute_data->called_scope) { - ce = execute_data->called_scope; + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else if (Z_CE(EX(This))) { + ce = Z_CE(EX(This)); } else { ce = zend_ce_error_exception; } - zend_throw_error(zend_ce_error, "Wrong parameters for %s([string $message [, long $code, [ long $severity, [ string $filename, [ long $lineno [, Throwable $previous = NULL]]]]]])", ZSTR_VAL(ce->name)); + 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)); return; } object = getThis(); if (message) { - zend_update_property_string(zend_ce_exception, object, "message", sizeof("message")-1, message); + ZVAL_STRING(&tmp, message); + zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_MESSAGE], &tmp); + zval_ptr_dtor(&tmp); } if (code) { - zend_update_property_long(zend_ce_exception, object, "code", sizeof("code")-1, code); + ZVAL_LONG(&tmp, code); + zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_CODE], &tmp); } if (previous) { - zend_update_property(zend_ce_exception, object, "previous", sizeof("previous")-1, previous); + zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_PREVIOUS], previous); } - zend_update_property_long(zend_ce_error_exception, object, "severity", sizeof("severity")-1, severity); + ZVAL_LONG(&tmp, severity); + zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_SEVERITY], &tmp); if (argc >= 4) { - zend_update_property_string(zend_ce_exception, object, "file", sizeof("file")-1, filename); + ZVAL_STRING(&tmp, filename); + zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_FILE], &tmp); + zval_ptr_dtor(&tmp); if (argc < 5) { lineno = 0; /* invalidate lineno */ } - zend_update_property_long(zend_ce_exception, object, "line", sizeof("line")-1, lineno); + ZVAL_LONG(&tmp, lineno); + zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_LINE], &tmp); } } /* }}} */ @@ -332,10 +388,10 @@ ZEND_METHOD(error_exception, __construct) return; \ } -#define GET_PROPERTY(object, name) \ - zend_read_property(i_get_exception_base(object), (object), name, sizeof(name) - 1, 0, &rv) -#define GET_PROPERTY_SILENT(object, name) \ - zend_read_property(i_get_exception_base(object), (object), name, sizeof(name) - 1, 1, &rv) +#define GET_PROPERTY(object, id) \ + zend_read_property_ex(i_get_exception_base(object), (object), CG(known_strings)[id], 0, &rv) +#define GET_PROPERTY_SILENT(object, id) \ + zend_read_property_ex(i_get_exception_base(object), (object), CG(known_strings)[id], 1, &rv) /* {{{ proto string Exception|Error::getFile() Get the file in which the exception occurred */ @@ -345,7 +401,7 @@ ZEND_METHOD(exception, getFile) DEFAULT_0_PARAMS; - ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "file")); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), ZEND_STR_FILE)); } /* }}} */ @@ -357,7 +413,7 @@ ZEND_METHOD(exception, getLine) DEFAULT_0_PARAMS; - ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "line")); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), ZEND_STR_LINE)); } /* }}} */ @@ -369,7 +425,7 @@ ZEND_METHOD(exception, getMessage) DEFAULT_0_PARAMS; - ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "message")); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), ZEND_STR_MESSAGE)); } /* }}} */ @@ -381,7 +437,7 @@ ZEND_METHOD(exception, getCode) DEFAULT_0_PARAMS; - ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "code")); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), ZEND_STR_CODE)); } /* }}} */ @@ -393,7 +449,7 @@ ZEND_METHOD(exception, getTrace) DEFAULT_0_PARAMS; - ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "trace")); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), ZEND_STR_TRACE)); } /* }}} */ @@ -405,80 +461,23 @@ ZEND_METHOD(error_exception, getSeverity) DEFAULT_0_PARAMS; - ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "severity")); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), ZEND_STR_SEVERITY)); } /* }}} */ #define TRACE_APPEND_KEY(key) do { \ - tmp = zend_hash_str_find(ht, key, sizeof(key)-1); \ + tmp = zend_hash_find(ht, key); \ if (tmp) { \ if (Z_TYPE_P(tmp) != IS_STRING) { \ - zend_error(E_WARNING, "Value for %s is no string", key); \ + zend_error(E_WARNING, "Value for %s is no string", \ + ZSTR_VAL(key)); \ smart_str_appends(str, "[unknown]"); \ } else { \ - smart_str_append(str, Z_STR_P(tmp)); \ + smart_str_appends(str, Z_STRVAL_P(tmp)); \ } \ } \ } while (0) -/* Windows uses VK_ESCAPE instead of \e */ -#ifndef VK_ESCAPE -#define VK_ESCAPE '\e' -#endif - -static size_t compute_escaped_string_len(const char *s, size_t l) { - size_t i, len = l; - for (i = 0; i < l; ++i) { - char c = s[i]; - if (c == '\n' || c == '\r' || c == '\t' || - c == '\f' || c == '\v' || c == '\\' || c == VK_ESCAPE) { - len += 1; - } else if (c < 32 || c > 126) { - len += 3; - } - } - return len; -} - -static void smart_str_append_escaped(smart_str *str, const char *s, size_t l) { - char *res; - size_t i, len = compute_escaped_string_len(s, l); - - smart_str_alloc(str, len, 0); - res = &ZSTR_VAL(str->s)[ZSTR_LEN(str->s)]; - ZSTR_LEN(str->s) += len; - - for (i = 0; i < l; ++i) { - unsigned char c = s[i]; - if (c < 32 || c == '\\' || c > 126) { - *res++ = '\\'; - switch (c) { - case '\n': *res++ = 'n'; break; - case '\r': *res++ = 'r'; break; - case '\t': *res++ = 't'; break; - case '\f': *res++ = 'f'; break; - case '\v': *res++ = 'v'; break; - case '\\': *res++ = '\\'; break; - case VK_ESCAPE: *res++ = 'e'; break; - default: - *res++ = 'x'; - if ((c >> 4) < 10) { - *res++ = (c >> 4) + '0'; - } else { - *res++ = (c >> 4) + 'A' - 10; - } - if ((c & 0xf) < 10) { - *res++ = (c & 0xf) + '0'; - } else { - *res++ = (c & 0xf) + 'A' - 10; - } - } - } else { - *res++ = c; - } - } -} - static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */ { /* the trivial way would be to do @@ -530,7 +529,7 @@ static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */ break; case IS_OBJECT: smart_str_appends(str, "Object("); - smart_str_append(str, Z_OBJCE_P(arg)->name); + smart_str_appends(str, ZSTR_VAL(Z_OBJCE_P(arg)->name)); smart_str_appends(str, "), "); break; } @@ -545,14 +544,14 @@ static void _build_trace_string(smart_str *str, HashTable *ht, uint32_t num) /* smart_str_append_long(str, num); smart_str_appendc(str, ' '); - file = zend_hash_str_find(ht, "file", sizeof("file")-1); + file = zend_hash_find(ht, CG(known_strings)[ZEND_STR_FILE]); if (file) { if (Z_TYPE_P(file) != IS_STRING) { zend_error(E_WARNING, "Function name is no string"); smart_str_appends(str, "[unknown function]"); } else{ zend_long line; - tmp = zend_hash_str_find(ht, "line", sizeof("line")-1); + tmp = zend_hash_find(ht, CG(known_strings)[ZEND_STR_LINE]); if (tmp) { if (Z_TYPE_P(tmp) == IS_LONG) { line = Z_LVAL_P(tmp); @@ -571,11 +570,11 @@ static void _build_trace_string(smart_str *str, HashTable *ht, uint32_t num) /* } else { smart_str_appends(str, "[internal function]: "); } - TRACE_APPEND_KEY("class"); - TRACE_APPEND_KEY("type"); - TRACE_APPEND_KEY("function"); + TRACE_APPEND_KEY(CG(known_strings)[ZEND_STR_CLASS]); + TRACE_APPEND_KEY(CG(known_strings)[ZEND_STR_TYPE]); + TRACE_APPEND_KEY(CG(known_strings)[ZEND_STR_FUNCTION]); smart_str_appendc(str, '('); - tmp = zend_hash_str_find(ht, "args", sizeof("args")-1); + tmp = zend_hash_find(ht, CG(known_strings)[ZEND_STR_ARGS]); if (tmp) { if (Z_TYPE_P(tmp) == IS_ARRAY) { size_t last_len = ZSTR_LEN(str->s); @@ -608,11 +607,11 @@ ZEND_METHOD(exception, getTraceAsString) uint32_t num = 0; DEFAULT_0_PARAMS; - + object = getThis(); base_ce = i_get_exception_base(object); - trace = zend_read_property(base_ce, object, "trace", sizeof("trace")-1, 1, &rv); + trace = zend_read_property_ex(base_ce, object, CG(known_strings)[ZEND_STR_TRACE], 1, &rv); if (Z_TYPE_P(trace) != IS_ARRAY) { RETURN_FALSE; } @@ -642,7 +641,7 @@ ZEND_METHOD(exception, getPrevious) DEFAULT_0_PARAMS; - ZVAL_COPY(return_value, GET_PROPERTY_SILENT(getThis(), "previous")); + ZVAL_COPY(return_value, GET_PROPERTY_SILENT(getThis(), ZEND_STR_PREVIOUS)); } /* }}} */ size_t zend_spprintf(char **message, size_t max_len, const char *format, ...) /* {{{ */ @@ -677,25 +676,24 @@ ZEND_METHOD(exception, __toString) zend_class_entry *base_ce; zend_string *str; zend_fcall_info fci; - zval fname, rv; + zval rv, tmp; + zend_string *fname; DEFAULT_0_PARAMS; str = ZSTR_EMPTY_ALLOC(); exception = getThis(); - ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1); + fname = zend_string_init("gettraceasstring", sizeof("gettraceasstring")-1, 0); - while (exception && Z_TYPE_P(exception) == IS_OBJECT) { + while (exception && Z_TYPE_P(exception) == IS_OBJECT && instanceof_function(Z_OBJCE_P(exception), zend_ce_throwable)) { zend_string *prev_str = str; - zend_string *message = zval_get_string(GET_PROPERTY(exception, "message")); - zend_string *file = zval_get_string(GET_PROPERTY(exception, "file")); - zend_long line = zval_get_long(GET_PROPERTY(exception, "line")); + zend_string *message = zval_get_string(GET_PROPERTY(exception, ZEND_STR_MESSAGE)); + zend_string *file = zval_get_string(GET_PROPERTY(exception, ZEND_STR_FILE)); + zend_long line = zval_get_long(GET_PROPERTY(exception, ZEND_STR_LINE)); fci.size = sizeof(fci); - fci.function_table = &Z_OBJCE_P(exception)->function_table; - ZVAL_COPY_VALUE(&fci.function_name, &fname); - fci.symbol_table = NULL; + ZVAL_STR(&fci.function_name, fname); fci.object = Z_OBJ_P(exception); fci.retval = &trace; fci.param_count = 0; @@ -734,16 +732,17 @@ ZEND_METHOD(exception, __toString) zend_string_release(file); zval_ptr_dtor(&trace); - exception = GET_PROPERTY(exception, "previous"); + exception = GET_PROPERTY(exception, ZEND_STR_PREVIOUS); } - zval_dtor(&fname); + zend_string_release(fname); exception = getThis(); base_ce = i_get_exception_base(exception); /* We store the result in the private property string so we can access * the result in uncaught exception handlers without memleaks. */ - zend_update_property_str(base_ce, exception, "string", sizeof("string")-1, str); + ZVAL_STR(&tmp, str); + zend_update_property_ex(base_ce, exception, CG(known_strings)[ZEND_STR_STRING], &tmp); RETURN_STR(str); } @@ -782,6 +781,7 @@ ZEND_END_ARG_INFO() static const zend_function_entry default_exception_functions[] = { ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL) ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC) + ZEND_ME(exception, __wakeup, NULL, ZEND_ACC_PUBLIC) ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) @@ -812,7 +812,7 @@ static const zend_function_entry error_exception_functions[] = { void zend_register_default_exception(void) /* {{{ */ { zend_class_entry ce; - + REGISTER_MAGIC_INTERFACE(throwable, Throwable); memcpy(&default_exception_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); @@ -868,7 +868,7 @@ void zend_register_default_exception(void) /* {{{ */ /* }}} */ /* {{{ Deprecated - Use zend_ce_exception directly instead */ -ZEND_API zend_class_entry *zend_exception_get_default(void) +ZEND_API zend_class_entry *zend_exception_get_default(void) { return zend_ce_exception; } @@ -881,9 +881,9 @@ ZEND_API zend_class_entry *zend_get_error_exception(void) } /* }}} */ -ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code) /* {{{ */ +ZEND_API ZEND_COLD zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code) /* {{{ */ { - zval ex; + zval ex, tmp; if (exception_ce) { if (!instanceof_function(exception_ce, zend_ce_throwable)) { @@ -897,10 +897,13 @@ ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const if (message) { - zend_update_property_string(exception_ce, &ex, "message", sizeof("message")-1, message); + ZVAL_STRING(&tmp, message); + zend_update_property_ex(exception_ce, &ex, CG(known_strings)[ZEND_STR_MESSAGE], &tmp); + zval_ptr_dtor(&tmp); } if (code) { - zend_update_property_long(exception_ce, &ex, "code", sizeof("code")-1, code); + ZVAL_LONG(&tmp, code); + zend_update_property_ex(exception_ce, &ex, CG(known_strings)[ZEND_STR_CODE], &tmp); } zend_throw_exception_internal(&ex); @@ -908,7 +911,7 @@ ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const } /* }}} */ -ZEND_API zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code, const char *format, ...) /* {{{ */ +ZEND_API ZEND_COLD zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code, const char *format, ...) /* {{{ */ { va_list arg; char *message; @@ -923,12 +926,13 @@ ZEND_API zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, ze } /* }}} */ -ZEND_API zend_object *zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, zend_long code, int severity) /* {{{ */ +ZEND_API ZEND_COLD zend_object *zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, zend_long code, int severity) /* {{{ */ { - zval ex; + zval ex, tmp; zend_object *obj = zend_throw_exception(exception_ce, message, code); ZVAL_OBJ(&ex, obj); - zend_update_property_long(zend_ce_error_exception, &ex, "severity", sizeof("severity")-1, severity); + ZVAL_LONG(&tmp, severity); + zend_update_property_ex(zend_ce_error_exception, &ex, CG(known_strings)[ZEND_STR_SEVERITY], &tmp); return obj; } /* }}} */ @@ -943,7 +947,7 @@ static void zend_error_va(int type, const char *file, uint lineno, const char *f } /* }}} */ -static void zend_error_helper(int type, const char *filename, const uint lineno, const char *format, ...) +static void zend_error_helper(int type, const char *filename, const uint lineno, const char *format, ...) /* {{{ */ { va_list va; @@ -951,9 +955,10 @@ static void zend_error_helper(int type, const char *filename, const uint lineno, zend_error_cb(type, filename, lineno, format, va); va_end(va); } +/* }}} */ /* This function doesn't return if it uses E_ERROR */ -ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */ +ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* {{{ */ { zval exception, rv; zend_class_entry *ce_exception; @@ -962,12 +967,11 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */ ce_exception = Z_OBJCE(exception); EG(exception) = NULL; if (ce_exception == zend_ce_parse_error) { - zend_string *message = zval_get_string(GET_PROPERTY(&exception, "message")); - zend_string *file = zval_get_string(GET_PROPERTY_SILENT(&exception, "file")); - zend_long line = zval_get_long(GET_PROPERTY_SILENT(&exception, "line")); - zend_long code = zval_get_long(GET_PROPERTY_SILENT(&exception, "code")); + zend_string *message = zval_get_string(GET_PROPERTY(&exception, ZEND_STR_MESSAGE)); + zend_string *file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE)); + zend_long line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE)); - zend_error_helper(code? code : E_ERROR, ZSTR_VAL(file), line, "%s", ZSTR_VAL(message)); + zend_error_helper(E_PARSE, ZSTR_VAL(file), line, "%s", ZSTR_VAL(message)); zend_string_release(file); zend_string_release(message); @@ -981,7 +985,7 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */ if (Z_TYPE(tmp) != IS_STRING) { zend_error(E_WARNING, "%s::__toString() must return a string", ZSTR_VAL(ce_exception->name)); } else { - zend_update_property_string(i_get_exception_base(&exception), &exception, "string", sizeof("string")-1, EG(exception) ? ZSTR_VAL(ce_exception->name) : Z_STRVAL(tmp)); + zend_update_property_ex(i_get_exception_base(&exception), &exception, CG(known_strings)[ZEND_STR_STRING], &tmp); } } zval_ptr_dtor(&tmp); @@ -992,8 +996,8 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */ ZVAL_OBJ(&zv, EG(exception)); /* do the best we can to inform about the inner exception */ if (instanceof_function(ce_exception, zend_ce_exception) || instanceof_function(ce_exception, zend_ce_error)) { - file = zval_get_string(GET_PROPERTY_SILENT(&zv, "file")); - line = zval_get_long(GET_PROPERTY_SILENT(&zv, "line")); + file = zval_get_string(GET_PROPERTY_SILENT(&zv, ZEND_STR_FILE)); + line = zval_get_long(GET_PROPERTY_SILENT(&zv, ZEND_STR_LINE)); } zend_error_va(E_WARNING, (file && ZSTR_LEN(file) > 0) ? ZSTR_VAL(file) : NULL, line, @@ -1005,9 +1009,9 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */ } } - str = zval_get_string(GET_PROPERTY_SILENT(&exception, "string")); - file = zval_get_string(GET_PROPERTY_SILENT(&exception, "file")); - line = zval_get_long(GET_PROPERTY_SILENT(&exception, "line")); + str = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_STRING)); + file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE)); + line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE)); zend_error_va(severity, (file && ZSTR_LEN(file) > 0) ? ZSTR_VAL(file) : NULL, line, "Uncaught %s\n thrown", ZSTR_VAL(str)); @@ -1022,7 +1026,7 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */ } /* }}} */ -ZEND_API void zend_throw_exception_object(zval *exception) /* {{{ */ +ZEND_API ZEND_COLD void zend_throw_exception_object(zval *exception) /* {{{ */ { zend_class_entry *exception_ce; @@ -1033,7 +1037,7 @@ ZEND_API void zend_throw_exception_object(zval *exception) /* {{{ */ exception_ce = Z_OBJCE_P(exception); if (!exception_ce || !instanceof_function(exception_ce, zend_ce_throwable)) { - zend_throw_error(zend_ce_error, "Cannot throw objects that do not implement Throwable"); + zend_throw_error(NULL, "Cannot throw objects that do not implement Throwable"); return; } zend_throw_exception_internal(exception); |