Make exception code more robust:

- Fix error in calculation of trace-string length
- Allow to overload __strostring() and make it work for uncaught exceptions
- Show exception thrown while displaying exceptions
This commit is contained in:
Marcus Boerger 2003-11-29 17:03:45 +00:00
parent b761414540
commit 9ffd44e94a
3 changed files with 81 additions and 18 deletions

View file

@ -2573,6 +2573,7 @@ void zend_do_declare_implicit_property(TSRMLS_D)
&& !zend_hash_exists(&CG(active_class_entry)->properties_info, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len+1)) {
znode property;
zend_error(E_STRICT, "Use of undefined property %s->%s", CG(active_class_entry)->name, opline_ptr->op2.u.constant.value.str.val);
property = opline_ptr->op2;
property.u.constant.value.str.val = estrndup(opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len);
zend_do_declare_property(&property, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_IMPLICIT_PUBLIC TSRMLS_CC);

View file

@ -303,6 +303,17 @@ ZEND_METHOD(exception, getTraceAsString)
}
/* }}} */
int zend_spprintf(char **message, int max_len, char *format, ...)
{
va_list arg;
int len;
va_start(arg, format);
len = zend_vspprintf(message, max_len, format, arg);
va_end(arg);
return len;
}
ZEND_METHOD(exception, __toString)
{
zval *message, *file, *line, *trace;
@ -329,12 +340,9 @@ ZEND_METHOD(exception, __toString)
zend_call_function(&fci, NULL TSRMLS_CC);
len = 11 + strlen(Z_OBJCE_P(getThis())->name) + 16 + Z_STRLEN_P(message) + 5 + Z_STRLEN_P(file) + 1 + MAX_LENGTH_OF_LONG + 14 + Z_STRLEN_P(trace) + 1;
str = emalloc(len);
sprintf(str, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s",
len = zend_spprintf(&str, 0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s",
Z_OBJCE_P(getThis())->name, Z_STRVAL_P(message), Z_STRVAL_P(file), Z_LVAL_P(line),
Z_STRLEN_P(trace) ? Z_STRVAL_P(trace) : "#0 {main}\n");
len = strlen(str);
/* We store the result in the private property string so we can access
* the result in uncaught exception handlers without memleaks. */
@ -485,14 +493,14 @@ ZEND_API void zend_exception_error(zval *exception TSRMLS_DC)
zend_fcall_info fci;
zval fname;
zval *str, *file, *line;
zval *old_exception = EG(exception);
file = zend_read_property(default_exception_ptr, exception, "file", sizeof("file")-1, 1 TSRMLS_CC);
line = zend_read_property(default_exception_ptr, exception, "line", sizeof("line")-1, 1 TSRMLS_CC);
EG(exception) = NULL;
ZVAL_STRINGL(&fname, "__tostring", sizeof("__tostring")-1, 0);
fci.size = sizeof(fci);
fci.function_table = &default_exception_ptr->function_table;
fci.function_table = &Z_OBJCE_P(exception)->function_table;
fci.function_name = &fname;
fci.symbol_table = NULL;
fci.object_pp = &exception;
@ -500,11 +508,34 @@ ZEND_API void zend_exception_error(zval *exception TSRMLS_DC)
fci.param_count = 0;
fci.params = NULL;
fci.no_separation = 1;
zend_call_function(&fci, NULL TSRMLS_CC);
zval_ptr_dtor(&str);
if (str) {
zend_update_property_string(default_exception_ptr, exception, "string", sizeof("string")-1, Z_STRVAL_P(str) TSRMLS_CC);
zval_ptr_dtor(&str);
} else if (EG(exception)) {
/* no result because of exception __tostring(), so at least return the class_name */
zend_update_property_string(default_exception_ptr, exception, "string", sizeof("string")-1, Z_OBJCE_P(exception)->name TSRMLS_CC);
}
if (EG(exception)) {
/* do the best we can to inform about the inner exception */
if (instanceof_function(Z_OBJCE_P(exception), default_exception_ptr TSRMLS_CC)) {
file = zend_read_property(default_exception_ptr, EG(exception), "file", sizeof("file")-1, 1 TSRMLS_CC);
line = zend_read_property(default_exception_ptr, EG(exception), "line", sizeof("line")-1, 1 TSRMLS_CC);
} else {
file = NULL;
line = NULL;
}
zend_error_va(E_WARNING, file ? Z_STRVAL_P(file) : NULL, line ? Z_LVAL_P(line) : 0, "Uncaught %s in exception handling during call to %s::__tostring()", Z_OBJCE_P(EG(exception))->name, Z_OBJCE_P(exception)->name);
}
str = zend_read_property(default_exception_ptr, exception, "string", sizeof("string")-1, 1 TSRMLS_CC);
file = zend_read_property(default_exception_ptr, exception, "file", sizeof("file")-1, 1 TSRMLS_CC);
line = zend_read_property(default_exception_ptr, exception, "line", sizeof("line")-1, 1 TSRMLS_CC);
EG(exception) = old_exception;
zend_error_va(E_ERROR, Z_STRVAL_P(file), Z_LVAL_P(line), "Uncaught %s\n thrown", Z_STRVAL_P(str));
} else {

View file

@ -303,6 +303,17 @@ ZEND_METHOD(exception, getTraceAsString)
}
/* }}} */
int zend_spprintf(char **message, int max_len, char *format, ...)
{
va_list arg;
int len;
va_start(arg, format);
len = zend_vspprintf(message, max_len, format, arg);
va_end(arg);
return len;
}
ZEND_METHOD(exception, __toString)
{
zval *message, *file, *line, *trace;
@ -329,12 +340,9 @@ ZEND_METHOD(exception, __toString)
zend_call_function(&fci, NULL TSRMLS_CC);
len = 11 + strlen(Z_OBJCE_P(getThis())->name) + 16 + Z_STRLEN_P(message) + 5 + Z_STRLEN_P(file) + 1 + MAX_LENGTH_OF_LONG + 14 + Z_STRLEN_P(trace) + 1;
str = emalloc(len);
sprintf(str, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s",
len = zend_spprintf(&str, 0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s",
Z_OBJCE_P(getThis())->name, Z_STRVAL_P(message), Z_STRVAL_P(file), Z_LVAL_P(line),
Z_STRLEN_P(trace) ? Z_STRVAL_P(trace) : "#0 {main}\n");
len = strlen(str);
/* We store the result in the private property string so we can access
* the result in uncaught exception handlers without memleaks. */
@ -485,14 +493,14 @@ ZEND_API void zend_exception_error(zval *exception TSRMLS_DC)
zend_fcall_info fci;
zval fname;
zval *str, *file, *line;
zval *old_exception = EG(exception);
file = zend_read_property(default_exception_ptr, exception, "file", sizeof("file")-1, 1 TSRMLS_CC);
line = zend_read_property(default_exception_ptr, exception, "line", sizeof("line")-1, 1 TSRMLS_CC);
EG(exception) = NULL;
ZVAL_STRINGL(&fname, "__tostring", sizeof("__tostring")-1, 0);
fci.size = sizeof(fci);
fci.function_table = &default_exception_ptr->function_table;
fci.function_table = &Z_OBJCE_P(exception)->function_table;
fci.function_name = &fname;
fci.symbol_table = NULL;
fci.object_pp = &exception;
@ -500,11 +508,34 @@ ZEND_API void zend_exception_error(zval *exception TSRMLS_DC)
fci.param_count = 0;
fci.params = NULL;
fci.no_separation = 1;
zend_call_function(&fci, NULL TSRMLS_CC);
zval_ptr_dtor(&str);
if (str) {
zend_update_property_string(default_exception_ptr, exception, "string", sizeof("string")-1, Z_STRVAL_P(str) TSRMLS_CC);
zval_ptr_dtor(&str);
} else if (EG(exception)) {
/* no result because of exception __tostring(), so at least return the class_name */
zend_update_property_string(default_exception_ptr, exception, "string", sizeof("string")-1, Z_OBJCE_P(exception)->name TSRMLS_CC);
}
if (EG(exception)) {
/* do the best we can to inform about the inner exception */
if (instanceof_function(Z_OBJCE_P(exception), default_exception_ptr TSRMLS_CC)) {
file = zend_read_property(default_exception_ptr, EG(exception), "file", sizeof("file")-1, 1 TSRMLS_CC);
line = zend_read_property(default_exception_ptr, EG(exception), "line", sizeof("line")-1, 1 TSRMLS_CC);
} else {
file = NULL;
line = NULL;
}
zend_error_va(E_WARNING, file ? Z_STRVAL_P(file) : NULL, line ? Z_LVAL_P(line) : 0, "Uncaught %s in exception handling during call to %s::__tostring()", Z_OBJCE_P(EG(exception))->name, Z_OBJCE_P(exception)->name);
}
str = zend_read_property(default_exception_ptr, exception, "string", sizeof("string")-1, 1 TSRMLS_CC);
file = zend_read_property(default_exception_ptr, exception, "file", sizeof("file")-1, 1 TSRMLS_CC);
line = zend_read_property(default_exception_ptr, exception, "line", sizeof("line")-1, 1 TSRMLS_CC);
EG(exception) = old_exception;
zend_error_va(E_ERROR, Z_STRVAL_P(file), Z_LVAL_P(line), "Uncaught %s\n thrown", Z_STRVAL_P(str));
} else {