From: Nikita Popov Date: Mon, 10 Aug 2020 08:28:13 +0000 (+0200) Subject: Fixed bug #79948 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ee163161480f4196d618036728f4765de7139068;p=php Fixed bug #79948 Make sure we don't execute further scripts if one of them encountered an exit exception. Also make sure that we free file handles that end up unused due to an early abort in php_execute_scripts(), which turned up as an issue in the added test case. Finally, make use of EG(exit_status) in the places where we zend_eval_string_ex, instead of unconditionally assigning exit code 254. If an error occurs, the error handler will already set exit status 255. --- diff --git a/NEWS b/NEWS index 0ed3122f90..b8d4bd0643 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ PHP NEWS . Fixed bug #79946 (Build fails due to undeclared UINT32_C). (Nikita) . Fixed bug #77561 (Shebang line not stripped for non-primary script). (Nikita) + . Fixed bug #79948 (Exit in auto-prepended file does not abort PHP execution). + (Nikita) - Date: . Fixed bug #60302 (DateTime::createFromFormat should new static(), not new diff --git a/Zend/tests/bug79948.inc b/Zend/tests/bug79948.inc new file mode 100644 index 0000000000..b112b43c84 --- /dev/null +++ b/Zend/tests/bug79948.inc @@ -0,0 +1,2 @@ + +--EXPECT-- +Exiting... diff --git a/Zend/zend.c b/Zend/zend.c index 4b001c522c..2aa37b0536 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1674,12 +1674,19 @@ ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...) / int ret = SUCCESS; va_start(files, file_count); - for (i = 0; i < file_count && ret != FAILURE; i++) { + for (i = 0; i < file_count; i++) { file_handle = va_arg(files, zend_file_handle *); if (!file_handle) { continue; } + if (ret == FAILURE) { + /* If a failure occurred in one of the earlier files, + * only destroy the following file handles. */ + zend_file_handle_dtor(file_handle); + continue; + } + op_array = zend_compile_file(file_handle, type); if (file_handle->opened_path) { zend_hash_add_empty_element(&EG(included_files), file_handle->opened_path); diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index de95b2a8c0..2923165e56 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -973,8 +973,8 @@ ZEND_API ZEND_COLD int zend_exception_error(zend_object *ex, int severity) /* {{ zend_string_release_ex(str, 0); zend_string_release_ex(file, 0); } else if (ce_exception == &zend_ce_unwind_exit) { - /* We successfully unwound, nothing more to do */ - result = SUCCESS; + /* We successfully unwound, nothing more to do. + * We still return FAILURE in this case, as further execution should still be aborted. */ } else { zend_error(severity, "Uncaught exception %s", ZSTR_VAL(ce_exception->name)); } diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index 4874e0920c..81bad21ae6 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -979,9 +979,8 @@ static int do_cli(int argc, char **argv) /* {{{ */ break; case PHP_MODE_CLI_DIRECT: cli_register_file_handles(); - if (zend_eval_string_ex(exec_direct, NULL, "Command line code", 1) == FAILURE) { - exit_status=254; - } + zend_eval_string_ex(exec_direct, NULL, "Command line code", 1); + exit_status = EG(exit_status); break; case PHP_MODE_PROCESS_STDIN: @@ -993,7 +992,7 @@ static int do_cli(int argc, char **argv) /* {{{ */ cli_register_file_handles(); if (exec_begin && zend_eval_string_ex(exec_begin, NULL, "Command line begin code", 1) == FAILURE) { - exit_status=254; + exit_status = EG(exit_status); } while (exit_status == SUCCESS && (input=php_stream_gets(s_in_process, NULL, 0)) != NULL) { len = strlen(input); @@ -1006,7 +1005,7 @@ static int do_cli(int argc, char **argv) /* {{{ */ zend_hash_str_update(&EG(symbol_table), "argi", sizeof("argi")-1, &argi); if (exec_run) { if (zend_eval_string_ex(exec_run, NULL, "Command line run code", 1) == FAILURE) { - exit_status=254; + exit_status = EG(exit_status); } } else { if (script_file) { @@ -1022,7 +1021,7 @@ static int do_cli(int argc, char **argv) /* {{{ */ efree(input); } if (exec_end && zend_eval_string_ex(exec_end, NULL, "Command line end code", 1) == FAILURE) { - exit_status=254; + exit_status = EG(exit_status); } break;