diff options
author | Marcus Boerger <helly@php.net> | 2003-11-29 17:03:45 +0000 |
---|---|---|
committer | Marcus Boerger <helly@php.net> | 2003-11-29 17:03:45 +0000 |
commit | 9ffd44e94aa3f7e8bfb86dbc344225ee662e4769 (patch) | |
tree | dce02a0770100b4d2cc1fb09e9cd648dcb8ae910 | |
parent | b761414540830b522abbb14e7578dafc6b1e6d34 (diff) | |
download | php-git-9ffd44e94aa3f7e8bfb86dbc344225ee662e4769.tar.gz |
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
-rw-r--r-- | Zend/zend_compile.c | 1 | ||||
-rw-r--r-- | Zend/zend_default_classes.c | 49 | ||||
-rw-r--r-- | Zend/zend_exceptions.c | 49 |
3 files changed, 81 insertions, 18 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 3440584e72..addc3db549 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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); diff --git a/Zend/zend_default_classes.c b/Zend/zend_default_classes.c index 2bbae70c0c..083bf9d170 100644 --- a/Zend/zend_default_classes.c +++ b/Zend/zend_default_classes.c @@ -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 { diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 2bbae70c0c..083bf9d170 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -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 { |