1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
/* 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 <windows.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) {
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);
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
|