Merge branch 'js/mingw-use-utf8'
authorJunio C Hamano <gitster@pobox.com>
Thu, 11 Jul 2019 22:16:49 +0000 (15:16 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 11 Jul 2019 22:16:49 +0000 (15:16 -0700)
Windows update.

* js/mingw-use-utf8:
mingw: fix possible buffer overrun when calling `GetUserNameW()`
mingw: use Unicode functions explicitly
mingw: get pw_name in UTF-8 format

1  2 
compat/mingw.c
compat/poll/poll.c
compat/winansi.c
diff --combined compat/mingw.c
index 433838391fd95d6c89279561df63176f31d77b27,a0eb695653ef3564c52360aa6a32032758d020e0..48917897710169fff29d93e5f1b5313cea871808
@@@ -1407,7 -1407,7 +1407,7 @@@ static pid_t mingw_spawnve_fd(const cha
        do_unset_environment_variables();
  
        /* Determine whether or not we are associated to a console */
-       cons = CreateFile("CONOUT$", GENERIC_WRITE,
+       cons = CreateFileW(L"CONOUT$", GENERIC_WRITE,
                        FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL, NULL);
        if (cons == INVALID_HANDLE_VALUE) {
@@@ -1553,10 -1553,7 +1553,10 @@@ static int try_shell_exec(const char *c
        if (prog) {
                int exec_id;
                int argc = 0;
 -              const char **argv2;
 +#ifndef _MSC_VER
 +              const
 +#endif
 +              char **argv2;
                while (argv[argc]) argc++;
                ALLOC_ARRAY(argv2, argc + 1);
                argv2[0] = (char *)cmd; /* full path to the script file */
@@@ -1949,13 -1946,19 +1949,19 @@@ struct passwd *getpwuid(int uid
        static unsigned initialized;
        static char user_name[100];
        static struct passwd *p;
+       wchar_t buf[100];
        DWORD len;
  
        if (initialized)
                return p;
  
-       len = sizeof(user_name);
-       if (!GetUserName(user_name, &len)) {
+       len = ARRAY_SIZE(buf);
+       if (!GetUserNameW(buf, &len)) {
+               initialized = 1;
+               return NULL;
+       }
+       if (xwcstoutf(user_name, buf, sizeof(user_name)) < 0) {
                initialized = 1;
                return NULL;
        }
@@@ -2119,33 -2122,8 +2125,33 @@@ int mingw_raise(int sig
                        sigint_fn(SIGINT);
                return 0;
  
 +#if defined(_MSC_VER)
 +      case SIGILL:
 +      case SIGFPE:
 +      case SIGSEGV:
 +      case SIGTERM:
 +      case SIGBREAK:
 +      case SIGABRT:
 +      case SIGABRT_COMPAT:
 +              /*
 +               * The <signal.h> header in the MS C Runtime defines 8 signals
 +               * as being supported on the platform. Anything else causes an
 +               * "Invalid signal or error" (which in DEBUG builds causes the
 +               * Abort/Retry/Ignore dialog). We by-pass the CRT for things we
 +               * already know will fail.
 +               */
 +              return raise(sig);
 +      default:
 +              errno = EINVAL;
 +              return -1;
 +
 +#else
 +
        default:
                return raise(sig);
 +
 +#endif
 +
        }
  }
  
@@@ -2329,13 -2307,18 +2335,13 @@@ static void setup_windows_environment(v
                setenv("TERM", "cygwin", 1);
  }
  
 +#if !defined(_MSC_VER)
  /*
   * Disable MSVCRT command line wildcard expansion (__getmainargs called from
   * mingw startup code, see init.c in mingw runtime).
   */
  int _CRT_glob = 0;
 -
 -typedef struct {
 -      int newmode;
 -} _startupinfo;
 -
 -extern int __wgetmainargs(int *argc, wchar_t ***argv, wchar_t ***env, int glob,
 -              _startupinfo *si);
 +#endif
  
  static NORETURN void die_startup(void)
  {
@@@ -2413,40 -2396,21 +2419,40 @@@ static void maybe_redirect_std_handles(
                                  GENERIC_WRITE, FILE_FLAG_NO_BUFFERING);
  }
  
 -void mingw_startup(void)
 +#ifdef _MSC_VER
 +#ifdef _DEBUG
 +#include <crtdbg.h>
 +#endif
 +#endif
 +
 +/*
 + * We implement wmain() and compile with -municode, which would
 + * normally ignore main(), but we call the latter from the former
 + * so that we can handle non-ASCII command-line parameters
 + * appropriately.
 + *
 + * To be more compatible with the core git code, we convert
 + * argv into UTF8 and pass them directly to main().
 + */
 +int wmain(int argc, const wchar_t **wargv)
  {
 -      int i, maxlen, argc;
 -      char *buffer;
 -      wchar_t **wenv, **wargv;
 -      _startupinfo si;
 +      int i, maxlen, exit_status;
 +      char *buffer, **save;
 +      const char **argv;
  
        trace2_initialize_clock();
  
 -      maybe_redirect_std_handles();
 +#ifdef _MSC_VER
 +#ifdef _DEBUG
 +      _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
 +#endif
  
 -      /* get wide char arguments and environment */
 -      si.newmode = 0;
 -      if (__wgetmainargs(&argc, &wargv, &wenv, _CRT_glob, &si) < 0)
 -              die_startup();
 +#ifdef USE_MSVC_CRTDBG
 +      _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
 +#endif
 +#endif
 +
 +      maybe_redirect_std_handles();
  
        /* determine size of argv and environ conversion buffer */
        maxlen = wcslen(wargv[0]);
        maxlen = 3 * maxlen + 1;
        buffer = malloc_startup(maxlen);
  
 -      /* convert command line arguments and environment to UTF-8 */
 +      /*
 +       * Create a UTF-8 version of w_argv. Also create a "save" copy
 +       * to remember all the string pointers because parse_options()
 +       * will remove claimed items from the argv that we pass down.
 +       */
 +      ALLOC_ARRAY(argv, argc + 1);
 +      ALLOC_ARRAY(save, argc + 1);
        for (i = 0; i < argc; i++)
 -              __argv[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen);
 +              argv[i] = save[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen);
 +      argv[i] = save[i] = NULL;
        free(buffer);
  
        /* fix Windows specific environment settings */
  
        /* initialize Unicode console */
        winansi_init();
 +
 +      /* invoke the real main() using our utf8 version of argv. */
 +      exit_status = main(argc, argv);
 +
 +      for (i = 0; i < argc; i++)
 +              free(save[i]);
 +      free(save);
 +      free(argv);
 +
 +      return exit_status;
  }
  
  int uname(struct utsname *buf)
diff --combined compat/poll/poll.c
index 8b07edb0feca434cce2ff7766c30d7529febf996,8f24b802521e982bd9be6502854689bcd84906f4..0e95dd493c949122b22036bf5d205c413d4a0421
@@@ -149,8 -149,8 +149,8 @@@ win32_compute_revents (HANDLE h, int *p
      case FILE_TYPE_PIPE:
        if (!once_only)
        {
 -        NtQueryInformationFile = (PNtQueryInformationFile)
 +        NtQueryInformationFile = (PNtQueryInformationFile)(void (*)(void))
-           GetProcAddress (GetModuleHandle ("ntdll.dll"),
+           GetProcAddress (GetModuleHandleW (L"ntdll.dll"),
                            "NtQueryInformationFile");
          once_only = TRUE;
        }
diff --combined compat/winansi.c
index efc0abcdac43e1c126d6d8148b8a03392e4ae911,cd947e048e2c149240d636cc372b9f6de83700f9..cacd82c833a615a9daebbadca36d08647111a677
@@@ -7,7 -7,6 +7,7 @@@
  #include <wingdi.h>
  #include <winreg.h>
  #include "win32.h"
 +#include "win32/lazyload.h"
  
  static int fd_is_interactive[3] = { 0, 0, 0 };
  #define FD_CONSOLE 0x1
@@@ -42,21 -41,26 +42,21 @@@ typedef struct _CONSOLE_FONT_INFOEX 
  #endif
  #endif
  
 -typedef BOOL (WINAPI *PGETCURRENTCONSOLEFONTEX)(HANDLE, BOOL,
 -              PCONSOLE_FONT_INFOEX);
 -
  static void warn_if_raster_font(void)
  {
        DWORD fontFamily = 0;
 -      PGETCURRENTCONSOLEFONTEX pGetCurrentConsoleFontEx;
 +      DECLARE_PROC_ADDR(kernel32.dll, BOOL, GetCurrentConsoleFontEx,
 +                      HANDLE, BOOL, PCONSOLE_FONT_INFOEX);
  
        /* don't bother if output was ascii only */
        if (!non_ascii_used)
                return;
  
        /* GetCurrentConsoleFontEx is available since Vista */
 -      pGetCurrentConsoleFontEx = (PGETCURRENTCONSOLEFONTEX) GetProcAddress(
 -                      GetModuleHandle("kernel32.dll"),
 -                      "GetCurrentConsoleFontEx");
 -      if (pGetCurrentConsoleFontEx) {
 +      if (INIT_PROC_ADDR(GetCurrentConsoleFontEx)) {
                CONSOLE_FONT_INFOEX cfi;
                cfi.cbSize = sizeof(cfi);
 -              if (pGetCurrentConsoleFontEx(console, 0, &cfi))
 +              if (GetCurrentConsoleFontEx(console, 0, &cfi))
                        fontFamily = cfi.FontFamily;
        } else {
                /* pre-Vista: check default console font in registry */
@@@ -540,20 -544,7 +540,20 @@@ static HANDLE swap_osfhnd(int fd, HANDL
  #ifdef DETECT_MSYS_TTY
  
  #include <winternl.h>
 +
 +#if defined(_MSC_VER)
 +
 +typedef struct _OBJECT_NAME_INFORMATION
 +{
 +      UNICODE_STRING Name;
 +      WCHAR NameBuffer[0];
 +} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
 +
 +#define ObjectNameInformation 1
 +
 +#else
  #include <ntstatus.h>
 +#endif
  
  static void detect_msys_tty(int fd)
  {
@@@ -608,7 -599,7 +608,7 @@@ int winansi_isatty(int fd
  void winansi_init(void)
  {
        int con1, con2;
-       char name[32];
+       wchar_t name[32];
  
        /* check if either stdout or stderr is a console output screen buffer */
        con1 = is_console(1);
        }
  
        /* create a named pipe to communicate with the console thread */
-       xsnprintf(name, sizeof(name), "\\\\.\\pipe\\winansi%lu", GetCurrentProcessId());
-       hwrite = CreateNamedPipe(name, PIPE_ACCESS_OUTBOUND,
+       if (swprintf(name, ARRAY_SIZE(name) - 1, L"\\\\.\\pipe\\winansi%lu",
+                    GetCurrentProcessId()) < 0)
+               die("Could not initialize winansi pipe name");
+       hwrite = CreateNamedPipeW(name, PIPE_ACCESS_OUTBOUND,
                PIPE_TYPE_BYTE | PIPE_WAIT, 1, BUFFER_SIZE, 0, 0, NULL);
        if (hwrite == INVALID_HANDLE_VALUE)
                die_lasterr("CreateNamedPipe failed");
  
-       hread = CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
+       hread = CreateFileW(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
        if (hread == INVALID_HANDLE_VALUE)
                die_lasterr("CreateFile for named pipe failed");