diff --git a/Zend/tests/exception_011.phpt b/Zend/tests/exception_011.phpt new file mode 100644 index 000000000000..02bab1d11e3b Binary files /dev/null and b/Zend/tests/exception_011.phpt differ diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 14ae75e38d09..15f00fdea4ba 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -617,10 +617,26 @@ ZEND_METHOD(exception, __toString) } if (Z_STRLEN(message) > 0) { - len = zend_spprintf(&str, 0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s%s%s", - Z_OBJCE_P(exception)->name, Z_STRVAL(message), Z_STRVAL(file), Z_LVAL(line), - (trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n", - len ? "\n\nNext " : "", prev_str); + char *prefix, *suffix; + int prefix_len, suffix_len; + + prefix_len = zend_spprintf(&prefix, 0, "exception '%s' with message '", + Z_OBJCE_P(exception)->name); + + suffix_len = zend_spprintf(&suffix, 0, "' in %s:%ld\nStack trace:\n%s%s%s", + Z_STRVAL(file), Z_LVAL(line), + (trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n", + len ? "\n\nNext " : "", prev_str); + + len = prefix_len + Z_STRLEN(message) + suffix_len; + str = emalloc(len + 1); + memcpy(str, prefix, prefix_len); + memcpy(str + prefix_len, Z_STRVAL(message), Z_STRLEN(message)); + memcpy(str + prefix_len + Z_STRLEN(message), suffix, suffix_len); + str[len] = '\0'; + + efree(prefix); + efree(suffix); } else { len = zend_spprintf(&str, 0, "exception '%s' in %s:%ld\nStack trace:\n%s%s%s", Z_OBJCE_P(exception)->name, Z_STRVAL(file), Z_LVAL(line), @@ -643,7 +659,7 @@ ZEND_METHOD(exception, __toString) /* We store the result in the private property string so we can access * the result in uncaught exception handlers without memleaks. */ - zend_update_property_string(default_exception_ce, getThis(), "string", sizeof("string")-1, str TSRMLS_CC); + zend_update_property_stringl(default_exception_ce, getThis(), "string", sizeof("string")-1, str, len TSRMLS_CC); RETURN_STRINGL(str, len, 0); } @@ -807,7 +823,11 @@ ZEND_API void zend_exception_error(zval *exception, int severity TSRMLS_DC) /* { if (Z_TYPE_P(str) != IS_STRING) { zend_error(E_WARNING, "%s::__toString() must return a string", ce_exception->name); } else { - zend_update_property_string(default_exception_ce, exception, "string", sizeof("string")-1, EG(exception) ? ce_exception->name : Z_STRVAL_P(str) TSRMLS_CC); + if (EG(exception)) { + zend_update_property_string(default_exception_ce, exception, "string", sizeof("string")-1, ce_exception->name TSRMLS_CC); + } else { + zend_update_property_stringl(default_exception_ce, exception, "string", sizeof("string")-1, Z_STRVAL_P(str), Z_STRLEN_P(str) TSRMLS_CC); + } } } zval_ptr_dtor(&str); @@ -836,7 +856,7 @@ ZEND_API void zend_exception_error(zval *exception, int severity TSRMLS_DC) /* { convert_to_string(file); convert_to_long(line); - zend_error_va(severity, (Z_STRLEN_P(file) > 0) ? Z_STRVAL_P(file) : NULL, Z_LVAL_P(line), "Uncaught %s\n thrown", Z_STRVAL_P(str)); + zend_error_va(severity, (Z_STRLEN_P(file) > 0) ? Z_STRVAL_P(file) : NULL, Z_LVAL_P(line), "Uncaught %Z\n thrown", str); } else { zend_error(severity, "Uncaught exception '%s'", ce_exception->name); } diff --git a/main/main.c b/main/main.c index 2f56afa03a3f..6e8db5f1429a 100644 --- a/main/main.c +++ b/main/main.c @@ -1086,10 +1086,14 @@ static void php_error_cb(int type, const char *error_filename, const uint error_ if (type == E_ERROR || type == E_PARSE) { size_t len; char *buf = php_escape_html_entities(buffer, buffer_len, &len, 0, ENT_COMPAT, NULL TSRMLS_CC); - php_printf("%s
\n%s: %s in %s on line %d
\n%s", STR_PRINT(prepend_string), error_type_str, buf, error_filename, error_lineno, STR_PRINT(append_string)); + php_printf("%s
\n%s: ", STR_PRINT(prepend_string), error_type_str); + PHPWRITE(buf, len); + php_printf(" in %s on line %d
\n%s", error_filename, error_lineno, STR_PRINT(append_string)); efree(buf); } else { - php_printf("%s
\n%s: %s in %s on line %d
\n%s", STR_PRINT(prepend_string), error_type_str, buffer, error_filename, error_lineno, STR_PRINT(append_string)); + php_printf("%s
\n%s: ", STR_PRINT(prepend_string), error_type_str); + PHPWRITE(buffer, buffer_len); + php_printf(" in %s on line %d
\n%s", error_filename, error_lineno, STR_PRINT(append_string)); } } else { /* Write CLI/CGI errors to stderr if display_errors = "stderr" */ @@ -1097,13 +1101,19 @@ static void php_error_cb(int type, const char *error_filename, const uint error_ PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR ) { #ifdef PHP_WIN32 - fprintf(stderr, "%s: %s in %s on line %d\n", error_type_str, buffer, error_filename, error_lineno); + fprintf(stderr, "%s: ", error_type_str); + fwrite(buffer, buffer_len, 1, stderr); + fprintf(stderr, " in %s on line %d\n", error_filename, error_lineno); fflush(stderr); #else - fprintf(stderr, "%s: %s in %s on line %d\n", error_type_str, buffer, error_filename, error_lineno); + fprintf(stderr, "%s: ", error_type_str); + fwrite(buffer, buffer_len, 1, stderr); + fprintf(stderr, " in %s on line %d\n", error_filename, error_lineno); #endif } else { - php_printf("%s\n%s: %s in %s on line %d\n%s", STR_PRINT(prepend_string), error_type_str, buffer, error_filename, error_lineno, STR_PRINT(append_string)); + php_printf("%s\n%s: ", STR_PRINT(prepend_string), error_type_str); + PHPWRITE(buffer, buffer_len); + php_printf(" in %s on line %d\n%s", error_filename, error_lineno, STR_PRINT(append_string)); } } }