Skip to content

Commit db23350

Browse files
committed
Use clean shutdown on uncaught exception
1 parent aab1445 commit db23350

File tree

7 files changed

+26
-16
lines changed

7 files changed

+26
-16
lines changed

UPGRADING

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ PHP 8.0 UPGRADE NOTES
112112
. Unexpected characters in source files (such as null bytes outside of
113113
strings) will now result in a ParseError exception instead of a compile
114114
warning.
115+
. Uncaught exceptions now go through "clean shutdown", which means that
116+
destructors will be called after an uncaught exception.
115117

116118
- COM:
117119
. Removed the ability to import case-insensitive constants from type

Zend/tests/bug36268.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ Fatal error: Uncaught Error: Call to undefined function bar() in %sbug36268.php:
1515
Stack trace:
1616
#0 {main}
1717
thrown in %sbug36268.php on line 8
18+
Ha!

Zend/zend.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,7 +1246,7 @@ ZEND_API zval *zend_get_configuration_directive(zend_string *name) /* {{{ */
12461246
} while (0)
12471247

12481248
static ZEND_COLD void zend_error_va_list(
1249-
int type, const char *error_filename, uint32_t error_lineno,
1249+
int orig_type, const char *error_filename, uint32_t error_lineno,
12501250
const char *format, va_list args)
12511251
{
12521252
va_list usr_copy;
@@ -1258,6 +1258,7 @@ static ZEND_COLD void zend_error_va_list(
12581258
zend_stack loop_var_stack;
12591259
zend_stack delayed_oplines_stack;
12601260
zend_class_entry *orig_fake_scope;
1261+
int type = orig_type & E_ALL;
12611262

12621263
/* Report about uncaught exception in case of fatal errors */
12631264
if (EG(exception)) {
@@ -1304,7 +1305,7 @@ static ZEND_COLD void zend_error_va_list(
13041305
if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF
13051306
|| !(EG(user_error_handler_error_reporting) & type)
13061307
|| EG(error_handling) != EH_NORMAL) {
1307-
zend_error_cb(type, error_filename, error_lineno, format, args);
1308+
zend_error_cb(orig_type, error_filename, error_lineno, format, args);
13081309
} else switch (type) {
13091310
case E_ERROR:
13101311
case E_PARSE:
@@ -1313,7 +1314,7 @@ static ZEND_COLD void zend_error_va_list(
13131314
case E_COMPILE_ERROR:
13141315
case E_COMPILE_WARNING:
13151316
/* The error may not be safe to handle in user-space */
1316-
zend_error_cb(type, error_filename, error_lineno, format, args);
1317+
zend_error_cb(orig_type, error_filename, error_lineno, format, args);
13171318
break;
13181319
default:
13191320
/* Handle the error in user space */
@@ -1354,13 +1355,13 @@ static ZEND_COLD void zend_error_va_list(
13541355
if (call_user_function(CG(function_table), NULL, &orig_user_error_handler, &retval, 4, params) == SUCCESS) {
13551356
if (Z_TYPE(retval) != IS_UNDEF) {
13561357
if (Z_TYPE(retval) == IS_FALSE) {
1357-
zend_error_cb(type, error_filename, error_lineno, format, args);
1358+
zend_error_cb(orig_type, error_filename, error_lineno, format, args);
13581359
}
13591360
zval_ptr_dtor(&retval);
13601361
}
13611362
} else if (!EG(exception)) {
13621363
/* The user error handler failed, use built-in error handler */
1363-
zend_error_cb(type, error_filename, error_lineno, format, args);
1364+
zend_error_cb(orig_type, error_filename, error_lineno, format, args);
13641365
}
13651366

13661367
EG(fake_scope) = orig_fake_scope;
@@ -1626,9 +1627,10 @@ ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...) /
16261627
int i;
16271628
zend_file_handle *file_handle;
16281629
zend_op_array *op_array;
1630+
int ret = SUCCESS;
16291631

16301632
va_start(files, file_count);
1631-
for (i = 0; i < file_count; i++) {
1633+
for (i = 0; i < file_count && ret != FAILURE; i++) {
16321634
file_handle = va_arg(files, zend_file_handle *);
16331635
if (!file_handle) {
16341636
continue;
@@ -1648,18 +1650,18 @@ ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...) /
16481650
}
16491651
if (EG(exception)) {
16501652
zend_exception_error(EG(exception), E_ERROR);
1653+
ret = FAILURE;
16511654
}
16521655
}
16531656
destroy_op_array(op_array);
16541657
efree_size(op_array, sizeof(zend_op_array));
16551658
} else if (type==ZEND_REQUIRE) {
1656-
va_end(files);
1657-
return FAILURE;
1659+
ret = FAILURE;
16581660
}
16591661
}
16601662
va_end(files);
16611663

1662-
return SUCCESS;
1664+
return ret;
16631665
}
16641666
/* }}} */
16651667

Zend/zend_errors.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
#define E_DEPRECATED (1<<13L)
3737
#define E_USER_DEPRECATED (1<<14L)
3838

39+
/* Indicates that this usually fatal error should not result in a bailout */
40+
#define E_DONT_BAIL (1<<15L)
41+
3942
#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)
4043
#define E_CORE (E_CORE_ERROR | E_CORE_WARNING)
4144

Zend/zend_exceptions.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,9 @@ ZEND_API ZEND_COLD void zend_throw_exception_internal(zval *exception) /* {{{ */
157157
if (exception && (Z_OBJCE_P(exception) == zend_ce_parse_error || Z_OBJCE_P(exception) == zend_ce_compile_error)) {
158158
return;
159159
}
160-
if(EG(exception)) {
160+
if (EG(exception)) {
161161
zend_exception_error(EG(exception), E_ERROR);
162+
zend_bailout();
162163
}
163164
zend_error_noreturn(E_CORE_ERROR, "Exception thrown without a stack frame");
164165
}
@@ -991,7 +992,8 @@ ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* {
991992
zend_string *file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE));
992993
zend_long line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE));
993994

994-
zend_error_helper(ce_exception == zend_ce_parse_error ? E_PARSE : E_COMPILE_ERROR,
995+
zend_error_helper(
996+
(ce_exception == zend_ce_parse_error ? E_PARSE : E_COMPILE_ERROR) | E_DONT_BAIL,
995997
ZSTR_VAL(file), line, "%s", ZSTR_VAL(message));
996998

997999
zend_string_release_ex(file, 0);
@@ -1034,7 +1036,8 @@ ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* {
10341036
file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE));
10351037
line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE));
10361038

1037-
zend_error_va(severity, (file && ZSTR_LEN(file) > 0) ? ZSTR_VAL(file) : NULL, line,
1039+
zend_error_va(severity | E_DONT_BAIL,
1040+
(file && ZSTR_LEN(file) > 0) ? ZSTR_VAL(file) : NULL, line,
10381041
"Uncaught %s\n thrown", ZSTR_VAL(str));
10391042

10401043
zend_string_release_ex(str, 0);

main/main.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,10 +1192,11 @@ PHPAPI void php_html_puts(const char *str, size_t size)
11921192

11931193
/* {{{ php_error_cb
11941194
extended error handling function */
1195-
static ZEND_COLD void php_error_cb(int type, const char *error_filename, const uint32_t error_lineno, const char *format, va_list args)
1195+
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)
11961196
{
11971197
char *buffer;
11981198
int buffer_len, display;
1199+
int type = orig_type & E_ALL;
11991200

12001201
buffer_len = (int)vspprintf(&buffer, PG(log_errors_max_len), format, args);
12011202

@@ -1403,7 +1404,7 @@ static ZEND_COLD void php_error_cb(int type, const char *error_filename, const u
14031404
sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
14041405
}
14051406
/* the parser would return 1 (failure), we can bail out nicely */
1406-
if (type != E_PARSE) {
1407+
if (!(orig_type & E_DONT_BAIL)) {
14071408
/* restore memory limit */
14081409
zend_set_memory_limit(PG(memory_limit));
14091410
efree(buffer);

sapi/cli/php_cli_server.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2202,8 +2202,6 @@ static int php_cli_server_dispatch_router(php_cli_server *server, php_cli_server
22022202
decline = Z_TYPE(retval) == IS_FALSE;
22032203
zval_ptr_dtor(&retval);
22042204
}
2205-
} else {
2206-
decline = 1;
22072205
}
22082206
} zend_end_try();
22092207

0 commit comments

Comments
 (0)