]> granicus.if.org Git - php/commitdiff
Make exception code more robust:
authorMarcus Boerger <helly@php.net>
Sat, 29 Nov 2003 17:03:45 +0000 (17:03 +0000)
committerMarcus Boerger <helly@php.net>
Sat, 29 Nov 2003 17:03:45 +0000 (17:03 +0000)
- 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

Zend/zend_compile.c
Zend/zend_default_classes.c
Zend/zend_exceptions.c

index 3440584e728ea16fbad0bdc84a1be03661137aab..addc3db549174d0da65bd80706d5126ba3bdff14 100644 (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);
index 2bbae70c0c1358eac8cf9f70cc43642e170bfa03..083bf9d1700b5916753924b0710482c3e6695da3 100644 (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 {
index 2bbae70c0c1358eac8cf9f70cc43642e170bfa03..083bf9d1700b5916753924b0710482c3e6695da3 100644 (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 {