summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-12-30 22:47:38 +0100
committerNikita Popov <nikita.ppv@gmail.com>2019-12-30 22:56:42 +0100
commitf77747b06c7623c4f673c75aebbe3372411a4275 (patch)
tree3cc7bba3949818ab66f236111d221926d296d805
parentd1537e506edb48790c72a93e1d8505ef2c3e4dd3 (diff)
downloadphp-git-f77747b06c7623c4f673c75aebbe3372411a4275.tar.gz
Properly propagate url_stat exceptions during include
Make sure we abort operations early, and that we don't emit additional warnings or errors if an exception has been thrown.
-rw-r--r--Zend/tests/bug60909_1.phpt4
-rw-r--r--Zend/tests/exception_during_include_stat.phpt41
-rw-r--r--Zend/zend_execute.c2
-rw-r--r--Zend/zend_language_scanner.l12
-rw-r--r--ext/standard/tests/filters/object_init_failure_2.phpt2
-rw-r--r--main/fopen_wrappers.c6
-rw-r--r--main/streams/streams.c3
7 files changed, 60 insertions, 10 deletions
diff --git a/Zend/tests/bug60909_1.phpt b/Zend/tests/bug60909_1.phpt
index e4c07face1..c82cf6c4d5 100644
--- a/Zend/tests/bug60909_1.phpt
+++ b/Zend/tests/bug60909_1.phpt
@@ -11,14 +11,12 @@ set_error_handler(function($errno, $errstr, $errfile, $errline){
require 'notfound.php';
--EXPECTF--
error(require(notfound.php): failed to open stream: %s)
-Warning: Uncaught Exception: Foo in %sbug60909_1.php:5
+Fatal error: Uncaught Exception: Foo in %sbug60909_1.php:5
Stack trace:
#0 %sbug60909_1.php(8): {closure}(2, 'require(notfoun...', '%s', 8, Array)
#1 %sbug60909_1.php(8): require()
#2 {main}
thrown in %sbug60909_1.php on line 5
-Fatal error: main(): Failed opening required 'notfound.php' (include_path='%s') in %sbug60909_1.php on line 8
-
!!!shutdown!!!
diff --git a/Zend/tests/exception_during_include_stat.phpt b/Zend/tests/exception_during_include_stat.phpt
new file mode 100644
index 0000000000..1927e7e251
--- /dev/null
+++ b/Zend/tests/exception_during_include_stat.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Make sure exceptions during include/require stating are properly propagated
+--FILE--
+<?php
+
+class StreamWrapper {
+ public function url_stat($path, $flags) {
+ throw new Exception('stat failed');
+ }
+}
+
+stream_wrapper_register('test', StreamWrapper::class);
+set_include_path('test://foo:test://bar');
+
+try {
+ require_once 'doesnt_exist.php';
+} catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ require 'doesnt_exist.php';
+} catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ include_once 'doesnt_exist.php';
+} catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ include 'doesnt_exist.php';
+} catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+stat failed
+stat failed
+stat failed
+stat failed
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 9ae73caae1..ab0d3656ee 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -4192,6 +4192,8 @@ static zend_never_inline zend_op_array* ZEND_FASTCALL zend_include_or_eval(zval
if (zend_hash_exists(&EG(included_files), resolved_path)) {
goto already_compiled;
}
+ } else if (UNEXPECTED(EG(exception))) {
+ break;
} else if (UNEXPECTED(strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename))) {
zend_message_dispatcher(
(type == ZEND_INCLUDE_ONCE) ?
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l
index 7dcb4dfcee..412356cdc1 100644
--- a/Zend/zend_language_scanner.l
+++ b/Zend/zend_language_scanner.l
@@ -637,11 +637,13 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type)
zend_save_lexical_state(&original_lex_state);
if (open_file_for_scanning(file_handle)==FAILURE) {
- if (type==ZEND_REQUIRE) {
- zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
- zend_bailout();
- } else {
- zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
+ if (!EG(exception)) {
+ if (type==ZEND_REQUIRE) {
+ zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
+ zend_bailout();
+ } else {
+ zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
+ }
}
} else {
op_array = zend_compile(ZEND_USER_FUNCTION);
diff --git a/ext/standard/tests/filters/object_init_failure_2.phpt b/ext/standard/tests/filters/object_init_failure_2.phpt
index 6a1458ff6a..a3ff299520 100644
--- a/ext/standard/tests/filters/object_init_failure_2.phpt
+++ b/ext/standard/tests/filters/object_init_failure_2.phpt
@@ -16,6 +16,4 @@ try {
Warning: main(): unable to create or locate filter "sample.filter" in %s on line %d
Warning: main(): Unable to create filter (sample.filter) in %s on line %d
-
-Warning: main(): Failed opening '%s' for inclusion (include_path='%s') in %s on line %d
Undefined constant 'FOO'
diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c
index b0bfa4feda..c85e0af7ab 100644
--- a/main/fopen_wrappers.c
+++ b/main/fopen_wrappers.c
@@ -561,6 +561,9 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt
if (SUCCESS == wrapper->wops->url_stat(wrapper, trypath, 0, &ssb, NULL)) {
return zend_string_init(trypath, strlen(trypath), 0);
}
+ if (EG(exception)) {
+ return NULL;
+ }
}
continue;
}
@@ -598,6 +601,9 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt
if (SUCCESS == wrapper->wops->url_stat(wrapper, trypath, 0, &ssb, NULL)) {
return zend_string_init(trypath, strlen(trypath), 0);
}
+ if (EG(exception)) {
+ return NULL;
+ }
}
return NULL;
}
diff --git a/main/streams/streams.c b/main/streams/streams.c
index 495feab100..ce370941a8 100644
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -2074,6 +2074,9 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(const char *path, const char *mod
options |= STREAM_ASSUME_REALPATH;
options &= ~USE_PATH;
}
+ if (EG(exception)) {
+ return NULL;
+ }
}
path_to_open = path;