diff --git a/Zend/zend.c b/Zend/zend.c
index a13884e5516a..311c20d1c4bd 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -1858,12 +1858,40 @@ ZEND_API ZEND_COLD void zend_user_exception_handler(void) /* {{{ */
zval_ptr_dtor(&orig_user_exception_handler);
} /* }}} */
+ZEND_API zend_result zend_execute_script(int type, zval *retval, zend_file_handle *file_handle)
+{
+ zend_op_array *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);
+ }
+
+ zend_result ret = SUCCESS;
+ if (op_array) {
+ zend_execute(op_array, retval);
+ zend_exception_restore();
+ if (UNEXPECTED(EG(exception))) {
+ if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
+ zend_user_exception_handler();
+ }
+ if (EG(exception)) {
+ ret = zend_exception_error(EG(exception), E_ERROR);
+ }
+ }
+ zend_destroy_static_vars(op_array);
+ destroy_op_array(op_array);
+ efree_size(op_array, sizeof(zend_op_array));
+ } else if (type == ZEND_REQUIRE) {
+ ret = FAILURE;
+ }
+
+ return ret;
+}
+
ZEND_API zend_result zend_execute_scripts(int type, zval *retval, int file_count, ...) /* {{{ */
{
va_list files;
int i;
zend_file_handle *file_handle;
- zend_op_array *op_array;
zend_result ret = SUCCESS;
va_start(files, file_count);
@@ -1872,32 +1900,10 @@ ZEND_API zend_result zend_execute_scripts(int type, zval *retval, int file_count
if (!file_handle) {
continue;
}
-
if (ret == FAILURE) {
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);
- }
- if (op_array) {
- zend_execute(op_array, retval);
- zend_exception_restore();
- if (UNEXPECTED(EG(exception))) {
- if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
- zend_user_exception_handler();
- }
- if (EG(exception)) {
- ret = zend_exception_error(EG(exception), E_ERROR);
- }
- }
- zend_destroy_static_vars(op_array);
- destroy_op_array(op_array);
- efree_size(op_array, sizeof(zend_op_array));
- } else if (type==ZEND_REQUIRE) {
- ret = FAILURE;
- }
+ ret = zend_execute_script(type, retval, file_handle);
}
va_end(files);
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index ca8e65413292..595bd86dcaca 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -867,6 +867,7 @@ ZEND_API zend_op_array *compile_filename(int type, zend_string *filename);
ZEND_API zend_ast *zend_compile_string_to_ast(
zend_string *code, struct _zend_arena **ast_arena, zend_string *filename);
ZEND_API zend_result zend_execute_scripts(int type, zval *retval, int file_count, ...);
+ZEND_API zend_result zend_execute_script(int type, zval *retval, zend_file_handle *file_handle);
ZEND_API zend_result open_file_for_scanning(zend_file_handle *file_handle);
ZEND_API void init_op_array(zend_op_array *op_array, uint8_t type, int initial_ops_size);
ZEND_API void destroy_op_array(zend_op_array *op_array);
diff --git a/ext/curl/tests/server.inc b/ext/curl/tests/server.inc
index 77df4558d57d..a7b177593db7 100644
--- a/ext/curl/tests/server.inc
+++ b/ext/curl/tests/server.inc
@@ -71,7 +71,7 @@ function curl_cli_server_start() {
}
register_shutdown_function(
- function($handle) use($router) {
+ function($handle) {
proc_terminate($handle);
/* Wait for server to shutdown */
for ($i = 0; $i < 60; $i++) {
diff --git a/main/main.c b/main/main.c
index b09e9bb99700..29d8642b8f71 100644
--- a/main/main.c
+++ b/main/main.c
@@ -2431,8 +2431,7 @@ void php_module_shutdown(void)
}
/* }}} */
-/* {{{ php_execute_script */
-PHPAPI bool php_execute_script(zend_file_handle *primary_file)
+PHPAPI bool php_execute_script_ex(zend_file_handle *primary_file, zval *retval)
{
zend_file_handle *prepend_file_p = NULL, *append_file_p = NULL;
zend_file_handle prepend_file, append_file;
@@ -2442,7 +2441,7 @@ PHPAPI bool php_execute_script(zend_file_handle *primary_file)
char *old_cwd;
ALLOCA_FLAG(use_heap)
#endif
- bool retval = false;
+ bool result = true;
#ifndef HAVE_BROKEN_GETCWD
# define OLD_CWD_SIZE 4096
@@ -2501,7 +2500,17 @@ PHPAPI bool php_execute_script(zend_file_handle *primary_file)
zend_set_timeout(INI_INT("max_execution_time"), 0);
}
- retval = (zend_execute_scripts(ZEND_REQUIRE, NULL, 3, prepend_file_p, primary_file, append_file_p) == SUCCESS);
+ if (prepend_file_p && result) {
+ result = zend_execute_script(ZEND_REQUIRE, NULL, prepend_file_p) == SUCCESS;
+ }
+ if (result) {
+ result = zend_execute_script(ZEND_REQUIRE, retval, primary_file) == SUCCESS;
+ }
+ if (append_file_p && result) {
+ result = zend_execute_script(ZEND_REQUIRE, NULL, append_file_p) == SUCCESS;
+ }
+ } zend_catch {
+ result = false;
} zend_end_try();
if (prepend_file_p) {
@@ -2529,7 +2538,13 @@ PHPAPI bool php_execute_script(zend_file_handle *primary_file)
}
free_alloca(old_cwd, use_heap);
#endif
- return retval;
+ return result;
+}
+
+/* {{{ php_execute_script */
+PHPAPI bool php_execute_script(zend_file_handle *primary_file)
+{
+ return php_execute_script_ex(primary_file, NULL);
}
/* }}} */
diff --git a/main/php_main.h b/main/php_main.h
index 213043b19b18..1fb460f07f26 100644
--- a/main/php_main.h
+++ b/main/php_main.h
@@ -45,6 +45,7 @@ PHPAPI int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals);
PHPAPI zend_result php_register_extensions(zend_module_entry * const * ptr, int count);
PHPAPI bool php_execute_script(zend_file_handle *primary_file);
+PHPAPI bool php_execute_script_ex(zend_file_handle *primary_file, zval *retval);
PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval *ret);
PHPAPI zend_result php_lint_script(zend_file_handle *file);
diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
index 05110e56a691..4382e8647c31 100644
--- a/sapi/cli/php_cli_server.c
+++ b/sapi/cli/php_cli_server.c
@@ -2241,20 +2241,13 @@ static bool php_cli_server_dispatch_router(php_cli_server *server, php_cli_serve
zend_try {
zval retval;
-
- /* Normally php_execute_script restarts the timer with max_execution_time if it has
- * previously been initialized with max_input_time. We're not using php_execute_script here
- * because it does not provide a way to get the return value of the main script, so we need
- * to restart the timer manually. */
- if (PG(max_input_time) != -1) {
-#ifdef PHP_WIN32
- zend_unset_timeout();
-#endif
- zend_set_timeout(INI_INT("max_execution_time"), 0);
- }
-
ZVAL_UNDEF(&retval);
- if (SUCCESS == zend_execute_scripts(ZEND_REQUIRE, &retval, 1, &zfd)) {
+ int sg_options_back = SG(options);
+ /* Don't chdir to the router script because the file path may be relative. */
+ SG(options) |= SAPI_OPTION_NO_CHDIR;
+ bool result = php_execute_script_ex(&zfd, &retval);
+ SG(options) = sg_options_back;
+ if (result) {
if (Z_TYPE(retval) != IS_UNDEF) {
decline = Z_TYPE(retval) == IS_FALSE;
zval_ptr_dtor(&retval);
diff --git a/sapi/cli/tests/gh13113.phpt b/sapi/cli/tests/gh13113.phpt
new file mode 100644
index 000000000000..5638bdf450d4
--- /dev/null
+++ b/sapi/cli/tests/gh13113.phpt
@@ -0,0 +1,38 @@
+--TEST--
+GH-13113: Missing syntax error in CLI-server router script
+--SKIPIF--
+
+--FILE--
+
+--EXPECTF--
+HTTP/1.1 200 OK
+Host: %s
+Date: %s
+Connection: close
+X-Powered-By: PHP/%s
+Content-type: text/html; charset=UTF-8
+
+
+Parse error: syntax error, unexpected identifier "bar" in %sindex.php on line 1