Piotr Caban : msvcrt: Fix IO initialization when invalid handles are passed.

Alexandre Julliard julliard at winehq.org
Wed Nov 15 16:46:00 CST 2017


Module: wine
Branch: master
Commit: 31bf13e92b1c6a7092a44240b763605ae315c328
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=31bf13e92b1c6a7092a44240b763605ae315c328

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Wed Nov 15 09:47:23 2017 +0100

msvcrt: Fix IO initialization when invalid handles are passed.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/msvcrt/file.c            | 42 +++++++++++++++++++++++++-----
 dlls/msvcrt/msvcrt.h          |  3 +++
 dlls/msvcrt/tests/Makefile.in |  1 +
 dlls/msvcrt/tests/file.c      | 59 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 98 insertions(+), 7 deletions(-)

diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c
index b22cbeb..2516570 100644
--- a/dlls/msvcrt/file.c
+++ b/dlls/msvcrt/file.c
@@ -581,30 +581,57 @@ void msvcrt_init_io(void)
   fdinfo = get_ioinfo_alloc_fd(MSVCRT_STDIN_FILENO);
   if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
     HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
+    DWORD flags = WX_OPEN | WX_TEXT;
     DWORD type = GetFileType(h);
 
-    msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
-            |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0));
+    if (type == FILE_TYPE_UNKNOWN) {
+        h = MSVCRT_NO_CONSOLE;
+        flags |= WX_TTY;
+    } else if ((type & 0xf) == FILE_TYPE_CHAR) {
+        flags |= WX_TTY;
+    } else if ((type & 0xf) == FILE_TYPE_PIPE) {
+        flags |= WX_PIPE;
+    }
+
+    msvcrt_set_fd(fdinfo, h, flags);
   }
   release_ioinfo(fdinfo);
 
   fdinfo = get_ioinfo_alloc_fd(MSVCRT_STDOUT_FILENO);
   if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
     HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
+    DWORD flags = WX_OPEN | WX_TEXT;
     DWORD type = GetFileType(h);
 
-    msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
-            |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0));
+    if (type == FILE_TYPE_UNKNOWN) {
+        h = MSVCRT_NO_CONSOLE;
+        flags |= WX_TTY;
+    } else if ((type & 0xf) == FILE_TYPE_CHAR) {
+        flags |= WX_TTY;
+    } else if ((type & 0xf) == FILE_TYPE_PIPE) {
+        flags |= WX_PIPE;
+    }
+
+    msvcrt_set_fd(fdinfo, h, flags);
   }
   release_ioinfo(fdinfo);
 
   fdinfo = get_ioinfo_alloc_fd(MSVCRT_STDERR_FILENO);
   if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
     HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
+    DWORD flags = WX_OPEN | WX_TEXT;
     DWORD type = GetFileType(h);
 
-    msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
-            |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0));
+    if (type == FILE_TYPE_UNKNOWN) {
+        h = MSVCRT_NO_CONSOLE;
+        flags |= WX_TTY;
+    } else if ((type & 0xf) == FILE_TYPE_CHAR) {
+        flags |= WX_TTY;
+    } else if ((type & 0xf) == FILE_TYPE_PIPE) {
+        flags |= WX_PIPE;
+    }
+
+    msvcrt_set_fd(fdinfo, h, flags);
   }
   release_ioinfo(fdinfo);
 
@@ -616,7 +643,8 @@ void msvcrt_init_io(void)
   for (i = 0; i < 3; i++)
   {
     /* FILE structs for stdin/out/err are static and never deleted */
-    MSVCRT__iob[i]._file = i;
+    MSVCRT__iob[i]._file = get_ioinfo_nolock(i)->handle == MSVCRT_NO_CONSOLE ?
+        MSVCRT_NO_CONSOLE_FD : i;
     MSVCRT__iob[i]._tmpfname = NULL;
     MSVCRT__iob[i]._flag = (i == 0) ? MSVCRT__IOREAD : MSVCRT__IOWRT;
   }
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index 1b117c8..a380613 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -742,6 +742,9 @@ struct MSVCRT__stat64 {
 #define MSVCRT_SEEK_CUR  1
 #define MSVCRT_SEEK_END  2
 
+#define MSVCRT_NO_CONSOLE_FD (-2)
+#define MSVCRT_NO_CONSOLE ((HANDLE)MSVCRT_NO_CONSOLE_FD)
+
 #define MSVCRT_STDIN_FILENO  0
 #define MSVCRT_STDOUT_FILENO 1
 #define MSVCRT_STDERR_FILENO 2
diff --git a/dlls/msvcrt/tests/Makefile.in b/dlls/msvcrt/tests/Makefile.in
index 2db553d..0867ac0 100644
--- a/dlls/msvcrt/tests/Makefile.in
+++ b/dlls/msvcrt/tests/Makefile.in
@@ -1,6 +1,7 @@
 TESTDLL   = msvcrt.dll
 APPMODE   = -mno-cygwin
 EXTRAINCL = -I$(srcdir)/..
+IMPORTS   = advapi32
 
 C_SRCS = \
 	cpp.c \
diff --git a/dlls/msvcrt/tests/file.c b/dlls/msvcrt/tests/file.c
index d92a6e4..e0b94cf 100644
--- a/dlls/msvcrt/tests/file.c
+++ b/dlls/msvcrt/tests/file.c
@@ -31,6 +31,7 @@
 #include <windef.h>
 #include <winbase.h>
 #include <winnls.h>
+#include <winreg.h>
 #include <process.h>
 #include <errno.h>
 #include <locale.h>
@@ -1522,6 +1523,61 @@ static void test_file_inherit( const char* selfname )
     DeleteFileA("fdopen.tst");
 }
 
+static void test_invalid_stdin_child( void )
+{
+    HANDLE handle;
+    ioinfo *info;
+
+    errno = 0xdeadbeef;
+    handle = (HANDLE)_get_osfhandle(STDIN_FILENO);
+    ok(handle == (HANDLE)-2, "handle = %p\n", handle);
+    ok(errno == 0xdeadbeef, "errno = %d\n", errno);
+
+    info = &__pioinfo[STDIN_FILENO/MSVCRT_FD_BLOCK_SIZE][STDIN_FILENO%MSVCRT_FD_BLOCK_SIZE];
+    ok(info->handle == (HANDLE)-2, "info->handle = %p\n", info->handle);
+    ok(info->wxflag == 0xc1, "info->wxflag = %x\n", info->wxflag);
+
+    ok(stdin->_file == -2, "stdin->_file = %d\n", stdin->_file);
+}
+
+static void test_invalid_stdin( const char* selfname )
+{
+    char cmdline[MAX_PATH];
+    PROCESS_INFORMATION proc;
+    SECURITY_ATTRIBUTES sa;
+    STARTUPINFOA startup;
+    HKEY key;
+    LONG ret;
+
+    if(!p_fopen_s) {
+        /* Behaviour of the dll has changed in newer version */
+        win_skip("skipping invalid stdin tests\n");
+        return;
+    }
+
+    ret = RegOpenCurrentUser(KEY_READ, &key);
+    ok(!ret, "RegOpenCurrentUser failed: %x\n", ret);
+
+    sa.nLength = sizeof(sa);
+    sa.lpSecurityDescriptor = NULL;
+    sa.bInheritHandle = TRUE;
+
+    memset(&startup, 0, sizeof(startup));
+    startup.cb = sizeof(startup);
+    startup.dwFlags = STARTF_USESTDHANDLES;
+    startup.hStdInput = key;
+    startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+    startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+
+    sprintf(cmdline, "%s file stdin", selfname);
+    CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
+            CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &proc);
+    winetest_wait_child_process(proc.hProcess);
+
+    ret = RegCloseKey(key);
+    ok(!ret, "RegCloseKey failed: %x\n", ret);
+}
+
 static void test_tmpnam( void )
 {
   char name[MAX_PATH] = "abc";
@@ -2461,12 +2517,15 @@ START_TEST(file)
             test_file_inherit_child_no(arg_v[3]);
         else if (strcmp(arg_v[2], "pipes") == 0)
             test_pipes_child(arg_c, arg_v);
+        else if (strcmp(arg_v[2], "stdin") == 0)
+            test_invalid_stdin_child();
         else
             ok(0, "invalid argument '%s'\n", arg_v[2]);
         return;
     }
     test_dup2();
     test_file_inherit(arg_v[0]);
+    test_invalid_stdin(arg_v[0]);
     test_file_write_read();
     test_chsize();
     test_stat();




More information about the wine-cvs mailing list