summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2019-08-20 16:04:14 +0200
committerChristoph M. Becker <cmbecker69@gmx.de>2019-08-20 16:04:14 +0200
commitc03114e55c7b9367fc9be895fe0df01cd1b62cab (patch)
treee738260fd074bb5d3287fa4dec208c075a07875b
parentae923287cada2bb59877e806c8219b74f7d857d5 (diff)
downloadphp-git-c03114e55c7b9367fc9be895fe0df01cd1b62cab.tar.gz
Fix #78386: fstat mode has unexpected value on PHP 7.4
We must not assume that any file which is not a directory is a regular file. Therefore we employ `GetFileType()` in this case to properly distinguish between character special, FIFO special and regular files.
-rw-r--r--NEWS1
-rw-r--r--ext/standard/tests/file/bug78386.phpt14
-rw-r--r--win32/ioutil.c15
3 files changed, 29 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index 013029cf2d..43a4745052 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,7 @@ PHP NEWS
. Fixed bug #78406 (Broken file includes with user-defined stream filters).
(Nikita)
. Fixed bug #72530 (Use After Free in GC with Certain Destructors). (Nikita)
+ . Fixed bug #78386 (fstat mode has unexpected value on PHP 7.4). (cmb)
- Date:
. Fixed bug #78383 (Casting a DateTime to array no longer returns its
diff --git a/ext/standard/tests/file/bug78386.phpt b/ext/standard/tests/file/bug78386.phpt
new file mode 100644
index 0000000000..9118761aab
--- /dev/null
+++ b/ext/standard/tests/file/bug78386.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Bug #78386 (fstat mode has unexpected value on PHP 7.4)
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') die("skip this test is for Windows platforms only");
+?>
+--FILE--
+<?php
+$handle = popen('dir', 'r');
+$stat = fstat($handle);
+var_dump(decoct($stat['mode']));
+?>
+--EXPECT--
+string(5) "10666"
diff --git a/win32/ioutil.c b/win32/ioutil.c
index 669876da38..f7db410dd2 100644
--- a/win32/ioutil.c
+++ b/win32/ioutil.c
@@ -942,7 +942,20 @@ static int php_win32_ioutil_fstat_int(HANDLE h, php_win32_ioutil_stat_t *buf, co
}
if ((data->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
- buf->st_mode |= is_dir ? (S_IFDIR|S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6)) : S_IFREG;
+ if (is_dir) {
+ buf->st_mode |= (S_IFDIR|S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6));
+ } else {
+ switch (GetFileType(h)) {
+ case FILE_TYPE_CHAR:
+ buf->st_mode |= S_IFCHR;
+ break;
+ case FILE_TYPE_PIPE:
+ buf->st_mode |= S_IFIFO;
+ break;
+ default:
+ buf->st_mode |= S_IFREG;
+ }
+ }
buf->st_mode |= (data->dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6)) : (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6)|S_IWRITE|(S_IWRITE>>3)|(S_IWRITE>>6));
}