diff options
Diffstat (limited to 'Zend/zend_exceptions.c')
-rw-r--r-- | Zend/zend_exceptions.c | 445 |
1 files changed, 189 insertions, 256 deletions
diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 6d5aa720fa..f9c1a509a6 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -28,6 +28,7 @@ #include "zend_exceptions.h" #include "zend_vm.h" #include "zend_dtrace.h" +#include "zend_smart_str.h" static zend_class_entry *default_exception_ce; static zend_class_entry *error_exception_ce; @@ -84,15 +85,12 @@ void zend_exception_restore(TSRMLS_D) /* {{{ */ } /* }}} */ -void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */ +ZEND_API void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */ { #ifdef HAVE_DTRACE if (DTRACE_EXCEPTION_THROWN_ENABLED()) { - zend_string *classname; - if (exception != NULL) { - classname = zend_get_object_classname(Z_OBJ_P(exception) TSRMLS_CC); - DTRACE_EXCEPTION_THROWN(classname->val); + DTRACE_EXCEPTION_THROWN(Z_OBJ_P(exception)->ce->val); } else { DTRACE_EXCEPTION_THROWN(NULL); } @@ -163,7 +161,7 @@ static zend_object *zend_default_exception_new_ex(zend_class_entry *class_type, Z_SET_REFCOUNT(trace, 0); zend_update_property_string(default_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename(TSRMLS_C) TSRMLS_CC); - zend_update_property_int(default_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC); + zend_update_property_long(default_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC); zend_update_property(default_exception_ce, &obj, "trace", sizeof("trace")-1, &trace TSRMLS_CC); return object; @@ -196,7 +194,7 @@ ZEND_METHOD(exception, __clone) ZEND_METHOD(exception, __construct) { zend_string *message = NULL; - long code = 0; + zend_long code = 0; zval *object, *previous = NULL; int argc = ZEND_NUM_ARGS(); @@ -211,7 +209,7 @@ ZEND_METHOD(exception, __construct) } if (code) { - zend_update_property_int(default_exception_ce, object, "code", sizeof("code")-1, code TSRMLS_CC); + zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code TSRMLS_CC); } if (previous) { @@ -225,9 +223,10 @@ ZEND_METHOD(exception, __construct) ZEND_METHOD(error_exception, __construct) { char *message = NULL, *filename = NULL; - long code = 0, severity = E_ERROR, lineno; + zend_long code = 0, severity = E_ERROR, lineno; zval *object, *previous = NULL; - int argc = ZEND_NUM_ARGS(), message_len, filename_len; + int argc = ZEND_NUM_ARGS(); + size_t message_len, filename_len; if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|sllslO!", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno, &previous, default_exception_ce) == FAILURE) { zend_error(E_ERROR, "Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno [, Exception $previous = NULL]]]]]])"); @@ -240,21 +239,21 @@ ZEND_METHOD(error_exception, __construct) } if (code) { - zend_update_property_int(default_exception_ce, object, "code", sizeof("code")-1, code TSRMLS_CC); + zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code TSRMLS_CC); } if (previous) { zend_update_property(default_exception_ce, object, "previous", sizeof("previous")-1, previous TSRMLS_CC); } - zend_update_property_int(default_exception_ce, object, "severity", sizeof("severity")-1, severity TSRMLS_CC); + zend_update_property_long(default_exception_ce, object, "severity", sizeof("severity")-1, severity TSRMLS_CC); if (argc >= 4) { zend_update_property_string(default_exception_ce, object, "file", sizeof("file")-1, filename TSRMLS_CC); if (argc < 5) { lineno = 0; /* invalidate lineno */ } - zend_update_property_int(default_exception_ce, object, "line", sizeof("line")-1, lineno TSRMLS_CC); + zend_update_property_long(default_exception_ce, object, "line", sizeof("line")-1, lineno TSRMLS_CC); } } /* }}} */ @@ -264,14 +263,10 @@ ZEND_METHOD(error_exception, __construct) return; \ } -static void _default_exception_get_entry(zval *object, char *name, int name_len, zval *return_value TSRMLS_DC) /* {{{ */ -{ - zval *value; - - value = zend_read_property(default_exception_ce, object, name, name_len, 0 TSRMLS_CC); - ZVAL_COPY(return_value, value); -} -/* }}} */ +#define GET_PROPERTY(object, name) \ + zend_read_property(default_exception_ce, (object), name, sizeof(name) - 1, 0 TSRMLS_CC) +#define GET_PROPERTY_SILENT(object, name) \ + zend_read_property(default_exception_ce, (object), name, sizeof(name) - 1, 1 TSRMLS_CC) /* {{{ proto string Exception::getFile() Get the file in which the exception occurred */ @@ -279,7 +274,7 @@ ZEND_METHOD(exception, getFile) { DEFAULT_0_PARAMS; - _default_exception_get_entry(getThis(), "file", sizeof("file")-1, return_value TSRMLS_CC); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "file")); } /* }}} */ @@ -289,7 +284,7 @@ ZEND_METHOD(exception, getLine) { DEFAULT_0_PARAMS; - _default_exception_get_entry(getThis(), "line", sizeof("line")-1, return_value TSRMLS_CC); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "line")); } /* }}} */ @@ -299,7 +294,7 @@ ZEND_METHOD(exception, getMessage) { DEFAULT_0_PARAMS; - _default_exception_get_entry(getThis(), "message", sizeof("message")-1, return_value TSRMLS_CC); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "message")); } /* }}} */ @@ -309,7 +304,7 @@ ZEND_METHOD(exception, getCode) { DEFAULT_0_PARAMS; - _default_exception_get_entry(getThis(), "code", sizeof("code")-1, return_value TSRMLS_CC); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "code")); } /* }}} */ @@ -319,7 +314,7 @@ ZEND_METHOD(exception, getTrace) { DEFAULT_0_PARAMS; - _default_exception_get_entry(getThis(), "trace", sizeof("trace")-1, return_value TSRMLS_CC); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "trace")); } /* }}} */ @@ -329,50 +324,83 @@ ZEND_METHOD(error_exception, getSeverity) { DEFAULT_0_PARAMS; - _default_exception_get_entry(getThis(), "severity", sizeof("severity")-1, return_value TSRMLS_CC); + ZVAL_COPY(return_value, GET_PROPERTY(getThis(), "severity")); } /* }}} */ -/* {{{ gettraceasstring() macros */ -#define TRACE_APPEND_CHR(chr) \ - str = STR_REALLOC(str, str->len + 1, 0); \ - str->val[str->len - 1] = chr - -#define TRACE_APPEND_STRL(v, l) \ - { \ - str = STR_REALLOC(str, str->len + (l), 0); \ - memcpy(str->val + str->len - (l), (v), (l)); \ - } - -#define TRACE_APPEND_STR(v) \ - TRACE_APPEND_STRL((v), sizeof((v))-1) - #define TRACE_APPEND_KEY(key) do { \ tmp = zend_hash_str_find(ht, key, sizeof(key)-1); \ if (tmp) { \ if (Z_TYPE_P(tmp) != IS_STRING) { \ zend_error(E_WARNING, "Value for %s is no string", key); \ - TRACE_APPEND_STR("[unknown]"); \ + smart_str_appends(str, "[unknown]"); \ } else { \ - TRACE_APPEND_STRL(Z_STRVAL_P(tmp), Z_STRSIZE_P(tmp)); \ + smart_str_append(str, Z_STR_P(tmp)); \ } \ } \ } while (0) +/* Windows uses VK_ESCAPE instead of \e */ +#ifndef VK_ESCAPE +#define VK_ESCAPE '\e' +#endif -#define TRACE_ARG_APPEND(vallen) do { \ - int len = str->len; \ - str = STR_REALLOC(str, len + vallen, 0); \ - memmove(str->val + len - l_added + 1 + vallen, str->val + len - l_added + 1, l_added); \ - } while (0) +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 = &str->s->val[str->s->len]; + str->s->len += len; + + for (i = 0; i < l; ++i) { + 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, zend_string **str_ptr TSRMLS_DC) /* {{{ */ +static void _build_trace_args(zval *arg, smart_str *str TSRMLS_DC) /* {{{ */ { - zend_string *str = *str_ptr; - - /* the trivial way would be to do: + /* the trivial way would be to do * convert_to_string_ex(arg); * append it and kill the now tmp arg. * but that could cause some E_NOTICE and also damn long lines. @@ -381,163 +409,72 @@ static void _build_trace_args(zval *arg, zend_string **str_ptr TSRMLS_DC) /* {{{ ZVAL_DEREF(arg); switch (Z_TYPE_P(arg)) { case IS_NULL: - TRACE_APPEND_STR("NULL, "); + smart_str_appends(str, "NULL, "); break; - case IS_STRING: { - int l_added; - TRACE_APPEND_CHR('\''); - if (Z_STRSIZE_P(arg) > 15) { - TRACE_APPEND_STRL(Z_STRVAL_P(arg), 15); - TRACE_APPEND_STR("...', "); - l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */ + case IS_STRING: + smart_str_appendc(str, '\''); + smart_str_append_escaped(str, Z_STRVAL_P(arg), MIN(Z_STRLEN_P(arg), 15)); + if (Z_STRLEN_P(arg) > 15) { + smart_str_appends(str, "...', "); } else { - l_added = Z_STRSIZE_P(arg); - TRACE_APPEND_STRL(Z_STRVAL_P(arg), l_added); - TRACE_APPEND_STR("', "); - l_added += 3 + 1; - } - while (--l_added) { - unsigned char chr = str->val[str->len - l_added]; - if (chr < 32 || chr == '\\' || chr > 126) { - str->val[str->len - l_added] = '\\'; - - switch (chr) { - case '\n': - TRACE_ARG_APPEND(1); - str->val[str->len - l_added] = 'n'; - break; - case '\r': - TRACE_ARG_APPEND(1); - str->val[str->len - l_added] = 'r'; - break; - case '\t': - TRACE_ARG_APPEND(1); - str->val[str->len - l_added] = 't'; - break; - case '\f': - TRACE_ARG_APPEND(1); - str->val[str->len - l_added] = 'f'; - break; - case '\v': - TRACE_ARG_APPEND(1); - str->val[str->len - l_added] = 'v'; - break; -#ifndef PHP_WIN32 - case '\e': -#else - case VK_ESCAPE: -#endif - TRACE_ARG_APPEND(1); - str->val[str->len - l_added] = 'e'; - break; - case '\\': - TRACE_ARG_APPEND(1); - str->val[str->len - l_added] = '\\'; - break; - default: - TRACE_ARG_APPEND(3); - str->val[str->len - l_added - 2] = 'x'; - if ((chr >> 4) < 10) { - str->val[str->len - l_added - 1] = (chr >> 4) + '0'; - } else { - str->val[str->len - l_added - 1] = (chr >> 4) + 'A' - 10; - } - if (chr % 16 < 10) { - str->val[str->len - l_added] = chr % 16 + '0'; - } else { - str->val[str->len - l_added] = chr % 16 + 'A' - 10; - } - } - } + smart_str_appends(str, "', "); } break; - } case IS_FALSE: - TRACE_APPEND_STR("false, "); + smart_str_appends(str, "false, "); break; case IS_TRUE: - TRACE_APPEND_STR("true, "); + smart_str_appends(str, "true, "); break; - case IS_RESOURCE: { - zend_int_t lval = Z_RES_HANDLE_P(arg); - char s_tmp[MAX_LENGTH_OF_ZEND_INT + 1]; - int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */ - TRACE_APPEND_STR("Resource id #"); - TRACE_APPEND_STRL(s_tmp, l_tmp); - TRACE_APPEND_STR(", "); + case IS_RESOURCE: + smart_str_appends(str, "Resource id #"); + smart_str_append_long(str, Z_RES_HANDLE_P(arg)); + smart_str_appends(str, ", "); break; - } - case IS_INT: { - zend_int_t lval = Z_IVAL_P(arg); - char s_tmp[MAX_LENGTH_OF_ZEND_INT + 1]; - int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */ - TRACE_APPEND_STRL(s_tmp, l_tmp); - TRACE_APPEND_STR(", "); + case IS_LONG: + smart_str_append_long(str, Z_LVAL_P(arg)); + smart_str_appends(str, ", "); break; - } case IS_DOUBLE: { double dval = Z_DVAL_P(arg); - char *s_tmp; - int l_tmp; - - s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1); - l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval); /* SAFE */ - TRACE_APPEND_STRL(s_tmp, l_tmp); - /* %G already handles removing trailing zeros from the fractional part, yay */ + char *s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1); + int l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval); /* SAFE */ + smart_str_appendl(str, s_tmp, l_tmp); + smart_str_appends(str, ", "); efree(s_tmp); - TRACE_APPEND_STR(", "); break; } case IS_ARRAY: - TRACE_APPEND_STR("Array, "); + smart_str_appends(str, "Array, "); break; - case IS_OBJECT: { - zend_string *class_name; - - TRACE_APPEND_STR("Object("); - - class_name = zend_get_object_classname(Z_OBJ_P(arg) TSRMLS_CC); - - TRACE_APPEND_STRL(class_name->val, class_name->len); - TRACE_APPEND_STR("), "); - break; - } - default: + case IS_OBJECT: + smart_str_appends(str, "Object("); + smart_str_append(str, Z_OBJCE_P(arg)->name); + smart_str_appends(str, "), "); break; } - *str_ptr = str; } /* }}} */ -static void _build_trace_string(zval *frame, zend_uint_t index, zend_string **str_ptr, int *num TSRMLS_DC) /* {{{ */ +static void _build_trace_string(smart_str *str, HashTable *ht, uint32_t num TSRMLS_DC) /* {{{ */ { - char *s_tmp; - int len; - long line; - HashTable *ht; zval *file, *tmp; - zend_string *str = *str_ptr; - if (Z_TYPE_P(frame) != IS_ARRAY) { - zend_error(E_WARNING, "Expected array for frame %lu", index); - return; - } + smart_str_appendc(str, '#'); + smart_str_append_long(str, num); + smart_str_appendc(str, ' '); - ht = Z_ARRVAL_P(frame); - s_tmp = emalloc(1 + MAX_LENGTH_OF_ZEND_INT + 1 + 1); - len = sprintf(s_tmp, "#%d ", (*num)++); - TRACE_APPEND_STRL(s_tmp, len); - efree(s_tmp); file = zend_hash_str_find(ht, "file", sizeof("file")-1); if (file) { if (Z_TYPE_P(file) != IS_STRING) { zend_error(E_WARNING, "Function name is no string"); - TRACE_APPEND_STR("[unknown function]"); + smart_str_appends(str, "[unknown function]"); } else{ + zend_long line; tmp = zend_hash_str_find(ht, "line", sizeof("line")-1); if (tmp) { - if (Z_TYPE_P(tmp) == IS_INT) { - line = Z_IVAL_P(tmp); + if (Z_TYPE_P(tmp) == IS_LONG) { + line = Z_LVAL_P(tmp); } else { zend_error(E_WARNING, "Line is no long"); line = 0; @@ -545,37 +482,36 @@ static void _build_trace_string(zval *frame, zend_uint_t index, zend_string **st } else { line = 0; } - s_tmp = emalloc(Z_STRSIZE_P(file) + MAX_LENGTH_OF_ZEND_INT + 4 + 1); - len = sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_P(file), line); - TRACE_APPEND_STRL(s_tmp, len); - efree(s_tmp); + smart_str_append(str, Z_STR_P(file)); + smart_str_appendc(str, '('); + smart_str_append_long(str, line); + smart_str_appends(str, "): "); } } else { - TRACE_APPEND_STR("[internal function]: "); + smart_str_appends(str, "[internal function]: "); } TRACE_APPEND_KEY("class"); TRACE_APPEND_KEY("type"); TRACE_APPEND_KEY("function"); - TRACE_APPEND_CHR('('); + smart_str_appendc(str, '('); tmp = zend_hash_str_find(ht, "args", sizeof("args")-1); if (tmp) { if (Z_TYPE_P(tmp) == IS_ARRAY) { - int last_len = str->len; + size_t last_len = str->s->len; zval *arg; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(tmp), arg) { - _build_trace_args(arg, &str TSRMLS_CC); + _build_trace_args(arg, str TSRMLS_CC); } ZEND_HASH_FOREACH_END(); - if (last_len != str->len) { - str->len -= 2; /* remove last ', ' */ + if (last_len != str->s->len) { + str->s->len -= 2; /* remove last ', ' */ } } else { zend_error(E_WARNING, "args element is no array"); } } - TRACE_APPEND_STR(")\n"); - *str_ptr = str; + smart_str_appends(str, ")\n"); } /* }}} */ @@ -584,26 +520,28 @@ static void _build_trace_string(zval *frame, zend_uint_t index, zend_string **st ZEND_METHOD(exception, getTraceAsString) { zval *trace, *frame; - zend_uint_t index; - zend_string *str, *key; - int num = 0, len; - char s_tmp[MAX_LENGTH_OF_ZEND_INT + 7 + 1 + 1]; + zend_ulong index; + smart_str str = {0}; + uint32_t num = 0; DEFAULT_0_PARAMS; - str = STR_ALLOC(0, 0); - trace = zend_read_property(default_exception_ce, getThis(), "trace", sizeof("trace")-1, 1 TSRMLS_CC); - ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(trace), index, key, frame) { - _build_trace_string(frame, index, &str, &num TSRMLS_CC); - } ZEND_HASH_FOREACH_END(); + ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(trace), index, frame) { + if (Z_TYPE_P(frame) != IS_ARRAY) { + zend_error(E_WARNING, "Expected array for frame %pu", index); + continue; + } - len = sprintf(s_tmp, "#%d {main}", num); - TRACE_APPEND_STRL(s_tmp, len); + _build_trace_string(&str, Z_ARRVAL_P(frame), num++ TSRMLS_CC); + } ZEND_HASH_FOREACH_END(); - str->val[str->len] = '\0'; + smart_str_appendc(&str, '#'); + smart_str_append_long(&str, num); + smart_str_appends(&str, " {main}"); + smart_str_0(&str); - RETURN_NEW_STR(str); + RETURN_NEW_STR(str.s); } /* }}} */ @@ -611,18 +549,15 @@ ZEND_METHOD(exception, getTraceAsString) Return previous Exception or NULL. */ ZEND_METHOD(exception, getPrevious) { - zval *previous; - DEFAULT_0_PARAMS; - previous = zend_read_property(default_exception_ce, getThis(), "previous", sizeof("previous")-1, 1 TSRMLS_CC); - RETURN_ZVAL(previous, 1, 0); + ZVAL_COPY(return_value, GET_PROPERTY_SILENT(getThis(), "previous")); } /* }}} */ -int zend_spprintf(char **message, int max_len, const char *format, ...) /* {{{ */ +size_t zend_spprintf(char **message, size_t max_len, const char *format, ...) /* {{{ */ { va_list arg; - int len; + size_t len; va_start(arg, format); len = zend_vspprintf(message, max_len, format, arg); @@ -631,7 +566,7 @@ int zend_spprintf(char **message, int max_len, const char *format, ...) /* {{{ * } /* }}} */ -zend_string *zend_strpprintf(int max_len, const char *format, ...) /* {{{ */ +zend_string *zend_strpprintf(size_t max_len, const char *format, ...) /* {{{ */ { va_list arg; zend_string *str; @@ -647,8 +582,8 @@ zend_string *zend_strpprintf(int max_len, const char *format, ...) /* {{{ */ Obtain the string representation of the Exception object */ ZEND_METHOD(exception, __toString) { - zval message, file, line, trace, *exception; - zend_string *str, *prev_str; + zval trace, *exception; + zend_string *str; zend_fcall_info fci; zval fname; @@ -660,14 +595,10 @@ ZEND_METHOD(exception, __toString) ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1); while (exception && Z_TYPE_P(exception) == IS_OBJECT) { - prev_str = str; - _default_exception_get_entry(exception, "message", sizeof("message")-1, &message TSRMLS_CC); - _default_exception_get_entry(exception, "file", sizeof("file")-1, &file TSRMLS_CC); - _default_exception_get_entry(exception, "line", sizeof("line")-1, &line TSRMLS_CC); - - convert_to_string_ex(&message); - convert_to_string_ex(&file); - convert_to_int_ex(&line); + 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")); fci.size = sizeof(fci); fci.function_table = &Z_OBJCE_P(exception)->function_table; @@ -686,26 +617,26 @@ ZEND_METHOD(exception, __toString) ZVAL_UNDEF(&trace); } - if (Z_STRSIZE(message) > 0) { - str = zend_strpprintf(0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s%s%s", - Z_OBJCE_P(exception)->name->val, Z_STRVAL(message), Z_STRVAL(file), Z_IVAL(line), - (Z_TYPE(trace) == IS_STRING && Z_STRSIZE(trace)) ? Z_STRVAL(trace) : "#0 {main}\n", + if (message->len > 0) { + str = zend_strpprintf(0, "exception '%s' with message '%s' in %s:" ZEND_LONG_FMT + "\nStack trace:\n%s%s%s", + Z_OBJCE_P(exception)->name->val, message->val, file->val, line, + (Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n", prev_str->len ? "\n\nNext " : "", prev_str->val); } else { - str = zend_strpprintf(0, "exception '%s' in %s:%ld\nStack trace:\n%s%s%s", - Z_OBJCE_P(exception)->name->val, Z_STRVAL(file), Z_IVAL(line), - (Z_TYPE(trace) == IS_STRING && Z_STRSIZE(trace)) ? Z_STRVAL(trace) : "#0 {main}\n", + str = zend_strpprintf(0, "exception '%s' in %s:" ZEND_LONG_FMT + "\nStack trace:\n%s%s%s", + Z_OBJCE_P(exception)->name->val, file->val, line, + (Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n", prev_str->len ? "\n\nNext " : "", prev_str->val); } - STR_RELEASE(prev_str); - zval_dtor(&message); - zval_dtor(&file); - zval_dtor(&line); - - exception = zend_read_property(default_exception_ce, exception, "previous", sizeof("previous")-1, 0 TSRMLS_CC); + zend_string_release(prev_str); + zend_string_release(message); + zend_string_release(file); zval_ptr_dtor(&trace); + exception = GET_PROPERTY(exception, "previous"); } zval_dtor(&fname); @@ -775,7 +706,7 @@ void zend_register_default_exception(TSRMLS_D) /* {{{ */ zend_declare_property_string(default_exception_ce, "message", sizeof("message")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC); zend_declare_property_string(default_exception_ce, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC); - zend_declare_property_int(default_exception_ce, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_long(default_exception_ce, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED TSRMLS_CC); zend_declare_property_null(default_exception_ce, "file", sizeof("file")-1, ZEND_ACC_PROTECTED TSRMLS_CC); zend_declare_property_null(default_exception_ce, "line", sizeof("line")-1, ZEND_ACC_PROTECTED TSRMLS_CC); zend_declare_property_null(default_exception_ce, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE TSRMLS_CC); @@ -784,7 +715,7 @@ void zend_register_default_exception(TSRMLS_D) /* {{{ */ INIT_CLASS_ENTRY(ce, "ErrorException", error_exception_functions); error_exception_ce = zend_register_internal_class_ex(&ce, default_exception_ce TSRMLS_CC); error_exception_ce->create_object = zend_error_exception_new; - zend_declare_property_int(error_exception_ce, "severity", sizeof("severity")-1, E_ERROR, ZEND_ACC_PROTECTED TSRMLS_CC); + zend_declare_property_long(error_exception_ce, "severity", sizeof("severity")-1, E_ERROR, ZEND_ACC_PROTECTED TSRMLS_CC); } /* }}} */ @@ -800,7 +731,7 @@ ZEND_API zend_class_entry *zend_get_error_exception(TSRMLS_D) /* {{{ */ } /* }}} */ -ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, long code TSRMLS_DC) /* {{{ */ +ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code TSRMLS_DC) /* {{{ */ { zval ex; @@ -819,7 +750,7 @@ ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const zend_update_property_string(default_exception_ce, &ex, "message", sizeof("message")-1, message TSRMLS_CC); } if (code) { - zend_update_property_int(default_exception_ce, &ex, "code", sizeof("code")-1, code TSRMLS_CC); + zend_update_property_long(default_exception_ce, &ex, "code", sizeof("code")-1, code TSRMLS_CC); } zend_throw_exception_internal(&ex TSRMLS_CC); @@ -827,7 +758,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, long code TSRMLS_DC, const char *format, ...) /* {{{ */ +ZEND_API zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code TSRMLS_DC, const char *format, ...) /* {{{ */ { va_list arg; char *message; @@ -842,12 +773,12 @@ ZEND_API zend_object *zend_throw_exception_ex(zend_class_entry *exception_ce, lo } /* }}} */ -ZEND_API zend_object *zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, long code, int severity TSRMLS_DC) /* {{{ */ +ZEND_API zend_object *zend_throw_error_exception(zend_class_entry *exception_ce, const char *message, zend_long code, int severity TSRMLS_DC) /* {{{ */ { zval ex; zend_object *obj = zend_throw_exception(exception_ce, message, code TSRMLS_CC); ZVAL_OBJ(&ex, obj); - zend_update_property_int(default_exception_ce, &ex, "severity", sizeof("severity")-1, severity TSRMLS_CC); + zend_update_property_long(default_exception_ce, &ex, "severity", sizeof("severity")-1, severity TSRMLS_CC); return obj; } /* }}} */ @@ -871,7 +802,9 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity TSRMLS_DC) /* { ZVAL_OBJ(&exception, ex); ce_exception = Z_OBJCE(exception); if (instanceof_function(ce_exception, default_exception_ce TSRMLS_CC)) { - zval tmp, *str, *file, *line; + zval tmp; + zend_string *str, *file = NULL; + zend_long line = 0; EG(exception) = NULL; @@ -891,28 +824,28 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity TSRMLS_DC) /* { ZVAL_OBJ(&zv, EG(exception)); /* do the best we can to inform about the inner exception */ if (instanceof_function(ce_exception, default_exception_ce TSRMLS_CC)) { - file = zend_read_property(default_exception_ce, &zv, "file", sizeof("file")-1, 1 TSRMLS_CC); - line = zend_read_property(default_exception_ce, &zv, "line", sizeof("line")-1, 1 TSRMLS_CC); + file = zval_get_string(GET_PROPERTY_SILENT(&zv, "file")); + line = zval_get_long(GET_PROPERTY_SILENT(&zv, "line")); + } - convert_to_string_ex(file); - file = (Z_STRSIZE_P(file) > 0) ? file : NULL; - line = (Z_TYPE_P(line) == IS_INT) ? line : NULL; - } else { - file = NULL; - line = NULL; + zend_error_va(E_WARNING, (file && file->len > 0) ? file->val : NULL, line, + "Uncaught %s in exception handling during call to %s::__tostring()", + Z_OBJCE(zv)->name->val, ce_exception->name->val); + + if (file) { + zend_string_release(file); } - zend_error_va(E_WARNING, file ? Z_STRVAL_P(file) : NULL, line ? Z_IVAL_P(line) : 0, "Uncaught %s in exception handling during call to %s::__tostring()", Z_OBJCE(zv)->name->val, ce_exception->name->val); } - str = zend_read_property(default_exception_ce, &exception, "string", sizeof("string")-1, 1 TSRMLS_CC); - file = zend_read_property(default_exception_ce, &exception, "file", sizeof("file")-1, 1 TSRMLS_CC); - line = zend_read_property(default_exception_ce, &exception, "line", sizeof("line")-1, 1 TSRMLS_CC); + 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")); - convert_to_string_ex(str); - convert_to_string_ex(file); - convert_to_int_ex(line); + zend_error_va(severity, (file && file->len > 0) ? file->val : NULL, line, + "Uncaught %s\n thrown", str->val); - zend_error_va(severity, (Z_STRSIZE_P(file) > 0) ? Z_STRVAL_P(file) : NULL, Z_IVAL_P(line), "Uncaught %s\n thrown", Z_STRVAL_P(str)); + zend_string_release(str); + zend_string_release(file); } else { zend_error(severity, "Uncaught exception '%s'", ce_exception->name->val); } |