Bug 1572838 - ensure osint commandline args are passed appropriately, r=mhowell,mossop

Differential Revision: https://phabricator.services.mozilla.com/D42311

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Gijs Kruitbosch 2019-08-20 19:51:34 +00:00
parent c0db818712
commit 7b142a3c2b
5 changed files with 92 additions and 88 deletions

View File

@ -109,10 +109,7 @@ static mozilla::LauncherFlags ProcessCmdLine(int& aArgc, wchar_t* aArgv[]) {
result |= mozilla::LauncherFlags::eWaitForBrowser;
}
if (mozilla::CheckArg(
aArgc, aArgv, L"no-deelevate", static_cast<const wchar_t**>(nullptr),
mozilla::CheckArgFlag::CheckOSInt |
mozilla::CheckArgFlag::RemoveArg) == mozilla::ARG_FOUND) {
if (mozilla::CheckArg(aArgc, aArgv, L"no-deelevate") == mozilla::ARG_FOUND) {
result |= mozilla::LauncherFlags::eNoDeelevate;
}
@ -216,6 +213,8 @@ namespace mozilla {
Maybe<int> LauncherMain(int& argc, wchar_t* argv[],
const StaticXREAppData& aAppData) {
EnsureCommandlineSafe(argc, argv);
SetLauncherErrorAppData(aAppData);
if (CheckArg(argc, argv, L"log-launcher-error",

View File

@ -1254,8 +1254,7 @@ nsresult nsToolkitProfileService::SelectStartupProfile(
// Check the -profile command line argument. It accepts a single argument that
// gives the path to use for the profile.
ArgResult ar = CheckArg(*aArgc, aArgv, "profile", &arg,
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
ArgResult ar = CheckArg(*aArgc, aArgv, "profile", &arg);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: argument --profile requires a path\n");
return NS_ERROR_FAILURE;
@ -1298,8 +1297,7 @@ nsresult nsToolkitProfileService::SelectStartupProfile(
// Check the -createprofile command line argument. It accepts a single
// argument that is either the name for the new profile or the name followed
// by the path to use.
ar = CheckArg(*aArgc, aArgv, "createprofile", &arg,
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
ar = CheckArg(*aArgc, aArgv, "createprofile", &arg, CheckArgFlag::RemoveArg);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR,
"Error: argument --createprofile requires a profile name\n");
@ -1369,14 +1367,7 @@ nsresult nsToolkitProfileService::SelectStartupProfile(
return NS_ERROR_SHOW_PROFILE_MANAGER;
}
ar = CheckArg(*aArgc, aArgv, "profilemanager", (const char**)nullptr,
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR,
"Error: argument --profilemanager is invalid when argument "
"--osint is specified\n");
return NS_ERROR_FAILURE;
}
ar = CheckArg(*aArgc, aArgv, "profilemanager");
if (ar == ARG_FOUND) {
return NS_ERROR_SHOW_PROFILE_MANAGER;
}

View File

@ -88,7 +88,7 @@ inline bool strimatch(const wchar_t* lowerstr, const wchar_t* mixedstr) {
return internal::strimatch(&towlower, lowerstr, mixedstr);
}
enum class FlagLiteral { osint, safemode };
enum class FlagLiteral { osint, safemode, url };
template <typename CharT, FlagLiteral Literal>
inline const CharT* GetLiteral();
@ -106,11 +106,12 @@ inline const CharT* GetLiteral();
DECLARE_FLAG_LITERAL(osint, "osint")
DECLARE_FLAG_LITERAL(safemode, "safe-mode")
DECLARE_FLAG_LITERAL(url, "url")
enum class CheckArgFlag : uint32_t {
None = 0,
CheckOSInt = (1 << 0), // Retrun ARG_BAD if osint arg is also present.
RemoveArg = (1 << 1) // Remove the argument from the argv array.
// (1 << 0) Used to be CheckOSInt
RemoveArg = (1 << 1) // Remove the argument from the argv array.
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CheckArgFlag)
@ -188,19 +189,72 @@ inline ArgResult CheckArg(int& aArgc, CharT** aArgv, const CharT* aArg,
++curarg;
}
if ((aFlags & CheckArgFlag::CheckOSInt) && ar == ARG_FOUND) {
ArgResult arOSInt =
CheckArg(aArgc, aArgv, GetLiteral<CharT, FlagLiteral::osint>(),
static_cast<const CharT**>(nullptr), CheckArgFlag::None);
if (arOSInt == ARG_FOUND) {
ar = ARG_BAD;
#if defined(MOZILLA_INTERNAL_API)
PR_fprintf(PR_STDERR, "Error: argument --osint is invalid\n");
#endif // defined(MOZILLA_INTERNAL_API)
return ar;
}
template <typename CharT>
inline void EnsureCommandlineSafe(int& aArgc, CharT** aArgv) {
// We expect either no -osint, or the full commandline to be:
// app -osint -url foo
// If this varies, we abort to avoid abuse of other commandline handlers
// from apps that do a poor job escaping links they give to the OS.
const CharT* osintLit = GetLiteral<CharT, FlagLiteral::osint>();
if (CheckArg(aArgc, aArgv, osintLit, static_cast<const CharT**>(nullptr),
CheckArgFlag::None) == ARG_FOUND) {
// There should be 4 items left (app name + -osint + -url + param)
if (aArgc != 4) {
exit(127);
}
// The first should be osint.
CharT* arg = aArgv[1];
if (*arg != '-'
#ifdef XP_WIN
&& *arg != '/'
#endif
) {
exit(127);
}
++arg;
if (*arg == '-') {
++arg;
}
if (!strimatch(osintLit, arg)) {
exit(127);
}
// Strip it:
RemoveArg(aArgc, aArgv + 1);
// Now only the -url bit should be left:
arg = aArgv[1];
if (*arg != '-'
#ifdef XP_WIN
&& *arg != '/'
#endif
) {
exit(127);
}
++arg;
if (*arg == '-') {
++arg;
}
if (!strimatch(GetLiteral<CharT, FlagLiteral::url>(), arg)) {
exit(127);
}
// The param after url shouldn't be another switch:
arg = aArgv[2];
if (*arg == '-'
#ifdef XP_WIN
|| *arg == '/'
#endif
) {
exit(127);
}
}
return ar;
// Either no osint, so nothing to do, or we ensured nothing nefarious was
// passed.
}
#if defined(XP_WIN)

View File

@ -34,7 +34,7 @@ template <typename CharT>
inline Maybe<bool> IsSafeModeRequested(
int& aArgc, CharT* aArgv[],
const SafeModeFlag aFlags = SafeModeFlag::Unset) {
CheckArgFlag checkArgFlags = CheckArgFlag::CheckOSInt;
CheckArgFlag checkArgFlags = CheckArgFlag::None;
if (aFlags & SafeModeFlag::Unset) {
checkArgFlags |= CheckArgFlag::RemoveArg;
}

View File

@ -1975,26 +1975,12 @@ static nsresult SelectProfile(nsToolkitProfileService* aProfileSvc,
// reset-profile and migration args need to be checked before any profiles are
// chosen below.
ArgResult ar = CheckArg("reset-profile", nullptr,
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR,
"Error: argument --reset-profile is invalid when argument "
"--osint is specified\n");
return NS_ERROR_FAILURE;
}
ArgResult ar = CheckArg("reset-profile");
if (ar == ARG_FOUND) {
gDoProfileReset = true;
}
ar = CheckArg("migration", nullptr,
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR,
"Error: argument --migration is invalid when argument --osint "
"is specified\n");
return NS_ERROR_FAILURE;
}
ar = CheckArg("migration");
if (ar == ARG_FOUND) {
gDoMigration = true;
}
@ -3104,8 +3090,7 @@ int XREMain::XRE_mainInit(bool* aExitFlag) {
// Check for application.ini overrides
const char* override = nullptr;
ar = CheckArg("override", &override,
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
ar = CheckArg("override", &override);
if (ar == ARG_BAD) {
Output(true, "Incorrect number of arguments passed to --override");
return 1;
@ -3392,14 +3377,7 @@ int XREMain::XRE_mainInit(bool* aExitFlag) {
// Handle --no-remote and --new-instance command line arguments. Setup
// the environment to better accommodate other components and various
// restart scenarios.
ar = CheckArg("no-remote", nullptr,
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR,
"Error: argument --no-remote is invalid when argument --osint "
"is specified\n");
return 1;
}
ar = CheckArg("no-remote");
if (ar == ARG_FOUND || EnvHasValue("MOZ_NO_REMOTE")) {
mDisableRemoteClient = true;
mDisableRemoteServer = true;
@ -3408,14 +3386,7 @@ int XREMain::XRE_mainInit(bool* aExitFlag) {
}
}
ar = CheckArg("new-instance", nullptr,
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR,
"Error: argument --new-instance is invalid when argument "
"--osint is specified\n");
return 1;
}
ar = CheckArg("new-instance");
if (ar == ARG_FOUND || EnvHasValue("MOZ_NEW_INSTANCE")) {
mDisableRemoteClient = true;
}
@ -3426,15 +3397,7 @@ int XREMain::XRE_mainInit(bool* aExitFlag) {
CheckArg("new-instance");
#endif
ar = CheckArg("offline", nullptr,
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR,
"Error: argument --offline is invalid when argument --osint is "
"specified\n");
return 1;
}
ar = CheckArg("offline");
if (ar || EnvHasValue("XRE_START_OFFLINE")) {
mStartOffline = true;
}
@ -4619,9 +4582,15 @@ nsresult XREMain::XRE_mainRun() {
* .app/Contents/Resources.
*/
int XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) {
gArgc = argc;
gArgv = argv;
EnsureCommandlineSafe(gArgc, gArgv);
// DO NOT TOUCH THE COMMANDLINE ARGS BEFORE THIS!
ScopedLogging log;
mozilla::LogModule::Init(argc, argv);
mozilla::LogModule::Init(gArgc, gArgv);
#ifdef MOZ_CODE_COVERAGE
CodeCoverageHandler::Init();
@ -4633,9 +4602,6 @@ int XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) {
nsresult rv = NS_OK;
gArgc = argc;
gArgv = argv;
if (aConfig.appData) {
mAppData = MakeUnique<XREAppData>(*aConfig.appData);
} else {
@ -4861,13 +4827,10 @@ nsresult XRE_InitCommandLine(int aArgc, char* aArgv[]) {
recordreplay::parent::InitializeUIProcess(gArgc, gArgv);
const char* path = nullptr;
ArgResult ar = CheckArg("greomni", &path,
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
ArgResult ar = CheckArg("greomni", &path);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR,
"Error: argument --greomni requires a path argument or the "
"--osint argument was specified with the --appomni argument "
"which is invalid\n");
"Error: argument --greomni requires a path argument\n");
return NS_ERROR_FAILURE;
}
@ -4880,13 +4843,10 @@ nsresult XRE_InitCommandLine(int aArgc, char* aArgv[]) {
return rv;
}
ar = CheckArg("appomni", &path,
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
ar = CheckArg("appomni", &path);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR,
"Error: argument --appomni requires a path argument or the "
"--osint argument was specified with the --appomni argument "
"which is invalid\n");
"Error: argument --appomni requires a path argument\n");
return NS_ERROR_FAILURE;
}