diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /toolkit/xre/nsWindowsWMain.cpp | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/xre/nsWindowsWMain.cpp')
-rw-r--r-- | toolkit/xre/nsWindowsWMain.cpp | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/toolkit/xre/nsWindowsWMain.cpp b/toolkit/xre/nsWindowsWMain.cpp new file mode 100644 index 0000000000..ea14a59b80 --- /dev/null +++ b/toolkit/xre/nsWindowsWMain.cpp @@ -0,0 +1,176 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsWindowsWMain_cpp +#define nsWindowsWMain_cpp + +// This file is a .cpp file meant to be included in nsBrowserApp.cpp and other +// similar bootstrap code. It converts wide-character windows wmain into UTF-8 +// narrow-character strings. + +#ifndef XP_WIN +# error This file only makes sense on Windows. +#endif + +#include "mozilla/Char16.h" +#include "nsUTF8Utils.h" +#include "nsWindowsHelpers.h" + +#include <windows.h> +#include <versionhelpers.h> + +#ifdef __MINGW32__ + +/* MingW currently does not implement a wide version of the + startup routines. Workaround is to implement something like + it ourselves. See bug 411826 */ + +# include <shellapi.h> + +int wmain(int argc, WCHAR** argv); + +int main(int argc, char** argv) { + LPWSTR commandLine = GetCommandLineW(); + int argcw = 0; + LPWSTR* argvw = CommandLineToArgvW(commandLine, &argcw); + if (!argvw) return 127; + + int result = wmain(argcw, argvw); + LocalFree(argvw); + return result; +} +#endif /* __MINGW32__ */ + +#define main NS_internal_main + +#ifndef XRE_WANT_ENVIRON +int main(int argc, char** argv); +#else +int main(int argc, char** argv, char** envp); +#endif + +// SanitizeEnvironmentVariables() +// +// Mitigate CVE-2007-6753 (binary planting via unexpanded environment variable +// references) by forcibly expanding all environment variable references in +// %PATH%. +// +// CVE-2007-6753 is documented to have affected all active mainline Windows +// versions at the time of its announcement (i.e., up to Windows 7). Microsoft +// has never formally stated that later versions of Windows are free of this +// issue; out of an abundance of caution, we continue to mitigate it on Windows +// 8 and beyond. +static void SanitizeEnvironmentVariables() { + DWORD bufferSize = GetEnvironmentVariableW(L"PATH", nullptr, 0); + if (bufferSize) { + wchar_t* originalPath = new wchar_t[bufferSize]; + if (bufferSize - 1 == + GetEnvironmentVariableW(L"PATH", originalPath, bufferSize)) { + bufferSize = ExpandEnvironmentStringsW(originalPath, nullptr, 0); + // The maximum length of a Windows environment variable and the maximum + // length of a string returned by ExpandEnvironmentStringsW are both + // documented to be 32,767 characters. Under some versions of Windows, + // however, both may be longer, with delayed but deleterious consequences. + // + // We therefore cap the size manually, in case the user has a sufficiently + // problematic %PATH%. (See bug 1753910.) This is unlikely to occur unless + // there is some form of recursive referencing involved, in which case + // expansion is no mitigation anyway. + if (bufferSize && bufferSize < 32768) { + wchar_t* newPath = new wchar_t[bufferSize]; + if (ExpandEnvironmentStringsW(originalPath, newPath, bufferSize)) { + SetEnvironmentVariableW(L"PATH", newPath); + } + delete[] newPath; + } + } + delete[] originalPath; + } +} + +static char* AllocConvertUTF16toUTF8(char16ptr_t arg) { + // be generous... UTF16 units can expand up to 3 UTF8 units + size_t len = wcslen(arg); + // ConvertUTF16toUTF8 requires +1. Let's do that here, too, lacking + // knowledge of Windows internals. + size_t dstLen = len * 3 + 1; + char* s = new char[dstLen + 1]; // Another +1 for zero terminator + if (!s) return nullptr; + + int written = + ::WideCharToMultiByte(CP_UTF8, 0, arg, len, s, dstLen, nullptr, nullptr); + s[written] = 0; + return s; +} + +static void FreeAllocStrings(int argc, char** argv) { + while (argc) { + --argc; + delete[] argv[argc]; + } + + delete[] argv; +} + +int wmain(int argc, WCHAR** argv) { + // In Windows 7 32-bit, user32.dll must be mapped to the same virtual + // address in all processes. Otherwise, win32k's user-mode callback causes + // crash. Since we delayload user32.dll, if our code or injected code + // reserves the user32 address before user32.dll is loaded, it is loaded + // to a new address and we crash. To mitigate this problem, we explicitly + // load user32.dll as early as possible. See bug 1730033 for details. + if (!IsWindows8OrGreater()) { + SYSTEM_INFO sysInfo; + ::GetNativeSystemInfo(&sysInfo); + if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) { + LoadLibrarySystem32(L"user32.dll"); + } + } + + SanitizeEnvironmentVariables(); + SetDllDirectoryW(L""); + + // Only run this code if LauncherProcessWin.h was included beforehand, thus + // signalling that the hosting process should support launcher mode. +#if defined(mozilla_LauncherProcessWin_h) + mozilla::Maybe<int> launcherResult = + mozilla::LauncherMain(argc, argv, sAppData); + if (launcherResult) { + return launcherResult.value(); + } +#endif // defined(mozilla_LauncherProcessWin_h) + + char** argvConverted = new char*[argc + 1]; + if (!argvConverted) return 127; + + for (int i = 0; i < argc; ++i) { + argvConverted[i] = AllocConvertUTF16toUTF8(argv[i]); + if (!argvConverted[i]) { + return 127; + } + } + argvConverted[argc] = nullptr; + + // need to save argvConverted copy for later deletion. + char** deleteUs = new char*[argc + 1]; + if (!deleteUs) { + FreeAllocStrings(argc, argvConverted); + return 127; + } + for (int i = 0; i < argc; i++) deleteUs[i] = argvConverted[i]; +#ifndef XRE_WANT_ENVIRON + int result = main(argc, argvConverted); +#else + // Force creation of the multibyte _environ variable. + getenv("PATH"); + int result = main(argc, argvConverted, _environ); +#endif + + delete[] argvConverted; + FreeAllocStrings(argc, deleteUs); + + return result; +} + +#endif // nsWindowsWMain_cpp |