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.
This commit is contained in:
Nikita Popov 2020-08-10 10:28:13 +02:00
parent 1974522a2d
commit ee16316148
6 changed files with 29 additions and 9 deletions

2
NEWS
View File

@ -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

2
Zend/tests/bug79948.inc Normal file
View File

@ -0,0 +1,2 @@
<?php
exit("Exiting...\n");

10
Zend/tests/bug79948.phpt Normal file
View File

@ -0,0 +1,10 @@
--TEST--
Bug #79948: Exit in auto-prepended file does not abort PHP execution
--INI--
auto_prepend_file={PWD}/bug79948.inc
--FILE--
<?php
echo "Should not be executed.\n";
?>
--EXPECT--
Exiting...

View File

@ -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);

View File

@ -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));
}

View File

@ -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;