From 6c7cccdacc90c045aa30060ee883fa72f488b5cd Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 16 Apr 2021 15:28:47 +0200 Subject: [PATCH 1/4] Fix #80960: opendir() warning wrong info when failed on Windows Firstly, we must not forget to set appropriate error codes for "manual" checks in `virtual_file_ex()`. Secondly, we must not call `php_error_docref2()` for warnings regarding unary functions; thus, we introduce `php_win32_docref1_from_error()`. --- Zend/zend_virtual_cwd.c | 6 ++++++ main/main.c | 13 +++++++++++++ main/php.h | 1 + main/streams/plain_wrapper.c | 2 +- 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c index d1ec9e35ff2f7..7b0d05d63d651 100644 --- a/Zend/zend_virtual_cwd.c +++ b/Zend/zend_virtual_cwd.c @@ -1067,6 +1067,11 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func } #endif if (path_length + state_cwd_length + 1 >= MAXPATHLEN-1) { +#ifdef ZEND_WIN32 + SET_ERRNO_FROM_WIN32_CODE(ERROR_BUFFER_OVERFLOW); +#else + errno = ENAMETOOLONG; +#endif return 1; } memcpy(resolved_path, state->cwd, state_cwd_length); @@ -1095,6 +1100,7 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func #ifdef ZEND_WIN32 if (memchr(resolved_path, '*', path_length) || memchr(resolved_path, '?', path_length)) { + SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_NAME); return 1; } #endif diff --git a/main/main.c b/main/main.c index 1cb50ce1dd7bd..3450b4197f3d9 100644 --- a/main/main.c +++ b/main/main.c @@ -1180,6 +1180,19 @@ PHPAPI ZEND_COLD void php_error_docref2(const char *docref, const char *param1, /* }}} */ #ifdef PHP_WIN32 +PHPAPI ZEND_COLD void php_win32_docref1_from_error(DWORD error, const char *param1) { + char *buf = php_win32_error_to_msg(error); + size_t buf_len; + + buf_len = strlen(buf); + if (buf_len >= 2) { + buf[buf_len - 1] = '\0'; + buf[buf_len - 2] = '\0'; + } + php_error_docref1(NULL, param1, E_WARNING, "%s (code: %lu)", buf, error); + php_win32_error_msg_free(buf); +} + PHPAPI ZEND_COLD void php_win32_docref2_from_error(DWORD error, const char *param1, const char *param2) { char *buf = php_win32_error_to_msg(error); size_t buf_len; diff --git a/main/php.h b/main/php.h index dbd7673643bd7..c135a359f3748 100644 --- a/main/php.h +++ b/main/php.h @@ -346,6 +346,7 @@ PHPAPI ZEND_COLD void php_error_docref1(const char *docref, const char *param1, PHPAPI ZEND_COLD void php_error_docref2(const char *docref, const char *param1, const char *param2, int type, const char *format, ...) PHP_ATTRIBUTE_FORMAT(printf, 5, 6); #ifdef PHP_WIN32 +PHPAPI ZEND_COLD void php_win32_docref1_from_error(DWORD error, const char *param1); PHPAPI ZEND_COLD void php_win32_docref2_from_error(DWORD error, const char *param1, const char *param2); #endif END_EXTERN_C() diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index 8bd20969f9b0a..d187c23a59316 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -1018,7 +1018,7 @@ static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, const #ifdef PHP_WIN32 if (!dir) { - php_win32_docref2_from_error(GetLastError(), path, path); + php_win32_docref1_from_error(GetLastError(), path); } if (dir && dir->finished) { From c545908628fc8fed5d87de14e5fe6746ae722bf5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 16 Apr 2021 15:38:18 +0200 Subject: [PATCH 2/4] Add regression test --- ext/standard/tests/dir/bug80960.phpt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 ext/standard/tests/dir/bug80960.phpt diff --git a/ext/standard/tests/dir/bug80960.phpt b/ext/standard/tests/dir/bug80960.phpt new file mode 100644 index 0000000000000..d0434479f3013 --- /dev/null +++ b/ext/standard/tests/dir/bug80960.phpt @@ -0,0 +1,26 @@ +--TEST-- +Fix #80960 (opendir() warning wrong info when failed on Windows) +--SKIPIF-- + +--INI-- +log_errors_max_len=0 +--FILE-- + +--EXPECTF-- +Warning: opendir(notexist*): The filename, directory name, or volume label syntax is incorrect. (code: 123) in %s on line %d + +Warning: opendir(notexist*): failed to open dir: No such file or directory in %s on line %d + +Warning: opendir(notexist?): The filename, directory name, or volume label syntax is incorrect. (code: 123) in %s on line %d + +Warning: opendir(notexist?): failed to open dir: No such file or directory in %s on line %d + +Warning: opendir(longname__________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________): The file name is too long. (code: 111) in %s on line %d + +Warning: opendir(longname__________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________): failed to open dir: Filename too long in %s on line %d From 7f64d46daeaeb221f79dccb35f3f34bdd60972cf Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 19 Apr 2021 13:40:29 +0200 Subject: [PATCH 3/4] Adjust expectations of existing tests `opendir()` is a unary function, and as such must not report two arguments. --- ext/phar/tests/phar_buildfromdirectory2-win.phpt | 2 +- ext/phar/tests/phar_gobyebye-win32.phpt | 2 +- ext/standard/tests/dir/opendir_variation6-win32.phpt | 8 ++++---- ext/standard/tests/general_functions/bug44295-win.phpt | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/phar/tests/phar_buildfromdirectory2-win.phpt b/ext/phar/tests/phar_buildfromdirectory2-win.phpt index fd552302ae5e6..6b0151982f29d 100644 --- a/ext/phar/tests/phar_buildfromdirectory2-win.phpt +++ b/ext/phar/tests/phar_buildfromdirectory2-win.phpt @@ -26,5 +26,5 @@ __HALT_COMPILER(); ?> --EXPECTF-- %s(24) "UnexpectedValueException" -RecursiveDirectoryIterator::__construct(1,1): %s (code: 2) +RecursiveDirectoryIterator::__construct(1): %s (code: 2) ===DONE=== diff --git a/ext/phar/tests/phar_gobyebye-win32.phpt b/ext/phar/tests/phar_gobyebye-win32.phpt index ff7b685aac9b5..180467a5562dd 100644 --- a/ext/phar/tests/phar_gobyebye-win32.phpt +++ b/ext/phar/tests/phar_gobyebye-win32.phpt @@ -42,7 +42,7 @@ bool(false) bool(false) bool(false) -Warning: opendir(foo/hi,foo/hi): %s (code: 3) in phar://%sphar_gobyebye-win32.phar.php/foo/hi on line %d +Warning: opendir(foo/hi): %s (code: 3) in phar://%sphar_gobyebye-win32.phar.php/foo/hi on line %d Warning: opendir(foo/hi): failed to open dir: No such file or directory in phar://%sphar_gobyebye-win32.phar.php/foo/hi on line %d ===DONE=== diff --git a/ext/standard/tests/dir/opendir_variation6-win32.phpt b/ext/standard/tests/dir/opendir_variation6-win32.phpt index 3e3c26e6795f3..e01cf9c93b6c3 100644 --- a/ext/standard/tests/dir/opendir_variation6-win32.phpt +++ b/ext/standard/tests/dir/opendir_variation6-win32.phpt @@ -51,24 +51,24 @@ rmdir($dir_path); -- Wildcard = '*' -- -Warning: opendir(%s/opendir_var*,%s/opendir_var*): %s in %s on line %d +Warning: opendir(%s/opendir_var*): %s in %s on line %d Warning: opendir(%s/opendir_var*): failed to open dir: %s in %s on line %d bool(false) -Warning: opendir(%s/*,%s/*): %s in %s on line %d +Warning: opendir(%s/*): %s in %s on line %d Warning: opendir(%s/*): failed to open dir: %s in %s on line %d bool(false) -- Wildcard = '?' -- -Warning: opendir(%s/opendir_variation6/sub_dir?,%s/opendir_variation6/sub_dir?): %s in %s on line %d +Warning: opendir(%s/opendir_variation6/sub_dir?): %s in %s on line %d Warning: opendir(%s/opendir_variation6/sub_dir?): failed to open dir: %s in %s on line %d bool(false) -Warning: opendir(%s/opendir_variation6/sub?dir1,%s/opendir_variation6/sub?dir1): %s in %s on line %d +Warning: opendir(%s/opendir_variation6/sub?dir1): %s in %s on line %d Warning: opendir(%s/opendir_variation6/sub?dir1): failed to open dir: %s in %s on line %d bool(false) diff --git a/ext/standard/tests/general_functions/bug44295-win.phpt b/ext/standard/tests/general_functions/bug44295-win.phpt index 13a8918bcd3fc..e5eb4c26a941b 100644 --- a/ext/standard/tests/general_functions/bug44295-win.phpt +++ b/ext/standard/tests/general_functions/bug44295-win.phpt @@ -25,5 +25,5 @@ try { --EXPECTF-- before -in catch: DirectoryIterator::__construct(c:\not\exists\here,c:\not\exists\here): %s (code: 3) +in catch: DirectoryIterator::__construct(c:\not\exists\here): %s (code: 3) ==DONE== From 3ff1ca91b773e4f0964edcdfeda679297c71f958 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 19 Apr 2021 13:47:25 +0200 Subject: [PATCH 4/4] Make new test case more resilient The actual number of underscores varies depending on the path of the test case; let's not expect any particular number. Furthermore, we should not expect a certain failure message, since these are localized on Windows; it should be sufficient to check for the error code. --- ext/standard/tests/dir/bug80960.phpt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/standard/tests/dir/bug80960.phpt b/ext/standard/tests/dir/bug80960.phpt index d0434479f3013..703678de074a5 100644 --- a/ext/standard/tests/dir/bug80960.phpt +++ b/ext/standard/tests/dir/bug80960.phpt @@ -13,14 +13,14 @@ opendir("notexist?"); opendir(str_pad("longname", PHP_MAXPATHLEN - strlen(getcwd()), "_")); ?> --EXPECTF-- -Warning: opendir(notexist*): The filename, directory name, or volume label syntax is incorrect. (code: 123) in %s on line %d +Warning: opendir(notexist*): %s (code: 123) in %s on line %d Warning: opendir(notexist*): failed to open dir: No such file or directory in %s on line %d -Warning: opendir(notexist?): The filename, directory name, or volume label syntax is incorrect. (code: 123) in %s on line %d +Warning: opendir(notexist?): %s (code: 123) in %s on line %d Warning: opendir(notexist?): failed to open dir: No such file or directory in %s on line %d -Warning: opendir(longname__________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________): The file name is too long. (code: 111) in %s on line %d +Warning: opendir(longname%r_+%r): %s (code: 111) in %s on line %d -Warning: opendir(longname__________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________): failed to open dir: Filename too long in %s on line %d +Warning: opendir(longname%r_+%r): failed to open dir: Filename too long in %s on line %d