diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-10-10 14:14:36 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-10-11 12:41:15 +0200 |
commit | db233501ff9d56765ef4a870b777a643c2136711 (patch) | |
tree | dee39ce888124d9c70bff6e59ae62c580a983b37 | |
parent | aab1445b4c30e81b0725470b2fc3e8112449eb5f (diff) | |
download | php-git-db233501ff9d56765ef4a870b777a643c2136711.tar.gz |
Use clean shutdown on uncaught exception
-rw-r--r-- | UPGRADING | 2 | ||||
-rw-r--r-- | Zend/tests/bug36268.phpt | 1 | ||||
-rw-r--r-- | Zend/zend.c | 20 | ||||
-rw-r--r-- | Zend/zend_errors.h | 3 | ||||
-rw-r--r-- | Zend/zend_exceptions.c | 9 | ||||
-rw-r--r-- | main/main.c | 5 | ||||
-rw-r--r-- | sapi/cli/php_cli_server.c | 2 |
7 files changed, 26 insertions, 16 deletions
@@ -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 diff --git a/Zend/tests/bug36268.phpt b/Zend/tests/bug36268.phpt index 8c93186c73..3bec61ff49 100644 --- a/Zend/tests/bug36268.phpt +++ b/Zend/tests/bug36268.phpt @@ -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! diff --git a/Zend/zend.c b/Zend/zend.c index 4ad04f3876..ce98f50025 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -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; } /* }}} */ diff --git a/Zend/zend_errors.h b/Zend/zend_errors.h index 6fda0f843e..dd7539523d 100644 --- a/Zend/zend_errors.h +++ b/Zend/zend_errors.h @@ -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) diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 9fd0176c34..6dfb374c2c 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -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); diff --git a/main/main.c b/main/main.c index f5f523ac14..d24021a1fd 100644 --- a/main/main.c +++ b/main/main.c @@ -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); diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 3120d670f2..c6943a5442 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -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(); |