]> granicus.if.org Git - php/commitdiff
Use clean shutdown on uncaught exception
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 10 Oct 2019 12:14:36 +0000 (14:14 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 11 Oct 2019 10:41:15 +0000 (12:41 +0200)
UPGRADING
Zend/tests/bug36268.phpt
Zend/zend.c
Zend/zend_errors.h
Zend/zend_exceptions.c
main/main.c
sapi/cli/php_cli_server.c

index ea18a5052a6eb45df9bf8d29bddcbfa4e56b609b..7d26e2201904cf2529b547b295f3cec5b7deeeca 100644 (file)
--- a/UPGRADING
+++ b/UPGRADING
@@ -112,6 +112,8 @@ PHP 8.0 UPGRADE NOTES
   . Unexpected characters in source files (such as null bytes outside of
     strings) will now result in a ParseError exception instead of a compile
     warning.
+  . Uncaught exceptions now go through "clean shutdown", which means that
+    destructors will be called after an uncaught exception.
 
 - COM:
   . Removed the ability to import case-insensitive constants from type
index 8c93186c73cc5299d9d8ff574da83e40661cf597..3bec61ff49fbe4da9bd5757cbeb38df1ac9c1af9 100644 (file)
@@ -15,3 +15,4 @@ Fatal error: Uncaught Error: Call to undefined function bar() in %sbug36268.php:
 Stack trace:
 #0 {main}
   thrown in %sbug36268.php on line 8
+Ha!
index 4ad04f3876385c3b895c5b213654e92d5852af41..ce98f50025ffafa3ec7d60b0251017a3ee23fbef 100644 (file)
@@ -1246,7 +1246,7 @@ ZEND_API zval *zend_get_configuration_directive(zend_string *name) /* {{{ */
        } while (0)
 
 static ZEND_COLD void zend_error_va_list(
-               int type, const char *error_filename, uint32_t error_lineno,
+               int orig_type, const char *error_filename, uint32_t error_lineno,
                const char *format, va_list args)
 {
        va_list usr_copy;
@@ -1258,6 +1258,7 @@ static ZEND_COLD void zend_error_va_list(
        zend_stack loop_var_stack;
        zend_stack delayed_oplines_stack;
        zend_class_entry *orig_fake_scope;
+       int type = orig_type & E_ALL;
 
        /* Report about uncaught exception in case of fatal errors */
        if (EG(exception)) {
@@ -1304,7 +1305,7 @@ static ZEND_COLD void zend_error_va_list(
        if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF
                || !(EG(user_error_handler_error_reporting) & type)
                || EG(error_handling) != EH_NORMAL) {
-               zend_error_cb(type, error_filename, error_lineno, format, args);
+               zend_error_cb(orig_type, error_filename, error_lineno, format, args);
        } else switch (type) {
                case E_ERROR:
                case E_PARSE:
@@ -1313,7 +1314,7 @@ static ZEND_COLD void zend_error_va_list(
                case E_COMPILE_ERROR:
                case E_COMPILE_WARNING:
                        /* The error may not be safe to handle in user-space */
-                       zend_error_cb(type, error_filename, error_lineno, format, args);
+                       zend_error_cb(orig_type, error_filename, error_lineno, format, args);
                        break;
                default:
                        /* Handle the error in user space */
@@ -1354,13 +1355,13 @@ static ZEND_COLD void zend_error_va_list(
                        if (call_user_function(CG(function_table), NULL, &orig_user_error_handler, &retval, 4, params) == SUCCESS) {
                                if (Z_TYPE(retval) != IS_UNDEF) {
                                        if (Z_TYPE(retval) == IS_FALSE) {
-                                               zend_error_cb(type, error_filename, error_lineno, format, args);
+                                               zend_error_cb(orig_type, error_filename, error_lineno, format, args);
                                        }
                                        zval_ptr_dtor(&retval);
                                }
                        } else if (!EG(exception)) {
                                /* The user error handler failed, use built-in error handler */
-                               zend_error_cb(type, error_filename, error_lineno, format, args);
+                               zend_error_cb(orig_type, error_filename, error_lineno, format, args);
                        }
 
                        EG(fake_scope) = orig_fake_scope;
@@ -1626,9 +1627,10 @@ ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...) /
        int i;
        zend_file_handle *file_handle;
        zend_op_array *op_array;
+       int ret = SUCCESS;
 
        va_start(files, file_count);
-       for (i = 0; i < file_count; i++) {
+       for (i = 0; i < file_count && ret != FAILURE; i++) {
                file_handle = va_arg(files, zend_file_handle *);
                if (!file_handle) {
                        continue;
@@ -1648,18 +1650,18 @@ ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...) /
                                }
                                if (EG(exception)) {
                                        zend_exception_error(EG(exception), E_ERROR);
+                                       ret = FAILURE;
                                }
                        }
                        destroy_op_array(op_array);
                        efree_size(op_array, sizeof(zend_op_array));
                } else if (type==ZEND_REQUIRE) {
-                       va_end(files);
-                       return FAILURE;
+                       ret = FAILURE;
                }
        }
        va_end(files);
 
-       return SUCCESS;
+       return ret;
 }
 /* }}} */
 
index 6fda0f843e3bd24919d341ed750cd296743111d9..dd7539523dbf2427d9adf368b0422a955e09bc17 100644 (file)
@@ -36,6 +36,9 @@
 #define E_DEPRECATED           (1<<13L)
 #define E_USER_DEPRECATED      (1<<14L)
 
+/* Indicates that this usually fatal error should not result in a bailout */
+#define E_DONT_BAIL                    (1<<15L)
+
 #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_RECOVERABLE_ERROR | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT)
 #define E_CORE (E_CORE_ERROR | E_CORE_WARNING)
 
index 9fd0176c3446de48f91f7b1fcbdfbb9f750e324e..6dfb374c2cf83d63ba5ccf83bbe211b4f7f94e1d 100644 (file)
@@ -157,8 +157,9 @@ ZEND_API ZEND_COLD void zend_throw_exception_internal(zval *exception) /* {{{ */
                if (exception && (Z_OBJCE_P(exception) == zend_ce_parse_error || Z_OBJCE_P(exception) == zend_ce_compile_error)) {
                        return;
                }
-               if(EG(exception)) {
+               if (EG(exception)) {
                        zend_exception_error(EG(exception), E_ERROR);
+                       zend_bailout();
                }
                zend_error_noreturn(E_CORE_ERROR, "Exception thrown without a stack frame");
        }
@@ -991,7 +992,8 @@ ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* {
                zend_string *file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE));
                zend_long line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE));
 
-               zend_error_helper(ce_exception == zend_ce_parse_error ? E_PARSE : E_COMPILE_ERROR,
+               zend_error_helper(
+                       (ce_exception == zend_ce_parse_error ? E_PARSE : E_COMPILE_ERROR) | E_DONT_BAIL,
                        ZSTR_VAL(file), line, "%s", ZSTR_VAL(message));
 
                zend_string_release_ex(file, 0);
@@ -1034,7 +1036,8 @@ ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* {
                file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE));
                line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE));
 
-               zend_error_va(severity, (file && ZSTR_LEN(file) > 0) ? ZSTR_VAL(file) : NULL, line,
+               zend_error_va(severity | E_DONT_BAIL,
+                       (file && ZSTR_LEN(file) > 0) ? ZSTR_VAL(file) : NULL, line,
                        "Uncaught %s\n  thrown", ZSTR_VAL(str));
 
                zend_string_release_ex(str, 0);
index f5f523ac140de5bc60f83dc80409a95e8494740a..d24021a1fd0dfef461c871aedfb0ffdd8b644b1f 100644 (file)
@@ -1192,10 +1192,11 @@ PHPAPI void php_html_puts(const char *str, size_t size)
 
 /* {{{ php_error_cb
  extended error handling function */
-static ZEND_COLD void php_error_cb(int type, const char *error_filename, const uint32_t error_lineno, const char *format, va_list args)
+static ZEND_COLD void php_error_cb(int orig_type, const char *error_filename, const uint32_t error_lineno, const char *format, va_list args)
 {
        char *buffer;
        int buffer_len, display;
+       int type = orig_type & E_ALL;
 
        buffer_len = (int)vspprintf(&buffer, PG(log_errors_max_len), format, args);
 
@@ -1403,7 +1404,7 @@ static ZEND_COLD void php_error_cb(int type, const char *error_filename, const u
                                        sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
                                }
                                /* the parser would return 1 (failure), we can bail out nicely */
-                               if (type != E_PARSE) {
+                               if (!(orig_type & E_DONT_BAIL)) {
                                        /* restore memory limit */
                                        zend_set_memory_limit(PG(memory_limit));
                                        efree(buffer);
index 3120d670f211cd57b2f0e7bf153d31dab123d60e..c6943a5442a687c973eb388057b3dc9461210a05 100644 (file)
@@ -2202,8 +2202,6 @@ static int php_cli_server_dispatch_router(php_cli_server *server, php_cli_server
                                decline = Z_TYPE(retval) == IS_FALSE;
                                zval_ptr_dtor(&retval);
                        }
-               } else {
-                       decline = 1;
                }
        } zend_end_try();