Commit d851aa1e authored by skyostil's avatar skyostil Committed by Commit bot

base: Support command line wrappers with quoted arguments

Command line wrappers (e.g., --renderer-cmd-prefix) were previously
split into individual arguments purely based on whitespace. This fails
if the prefix has arguments with embedded whitespace (e.g., gdb -ex "set
height 0").

This patch fixes the issue by tokenizing the prefix based on whitespace
while using ' and " as quote characters.

BUG=546953

Review-Url: https://codereview.chromium.org/2778173003
Cr-Commit-Position: refs/heads/master@{#460443}
parent 158d97ab
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -411,11 +412,15 @@ void CommandLine::AppendArguments(const CommandLine& other, ...@@ -411,11 +412,15 @@ void CommandLine::AppendArguments(const CommandLine& other,
void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) { void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) {
if (wrapper.empty()) if (wrapper.empty())
return; return;
// The wrapper may have embedded arguments (like "gdb --args"). In this case, // Split the wrapper command based on whitespace (with quoting).
// we don't pretend to do anything fancy, we just split on spaces. using CommandLineTokenizer =
StringVector wrapper_argv = SplitString( StringTokenizerT<StringType, StringType::const_iterator>;
wrapper, FilePath::StringType(1, ' '), base::TRIM_WHITESPACE, CommandLineTokenizer tokenizer(wrapper, FILE_PATH_LITERAL(" "));
base::SPLIT_WANT_ALL); tokenizer.set_quote_chars(FILE_PATH_LITERAL("'\""));
std::vector<StringType> wrapper_argv;
while (tokenizer.GetNext())
wrapper_argv.emplace_back(tokenizer.token());
// Prepend the wrapper and update the switches/arguments |begin_args_|. // Prepend the wrapper and update the switches/arguments |begin_args_|.
argv_.insert(argv_.begin(), wrapper_argv.begin(), wrapper_argv.end()); argv_.insert(argv_.begin(), wrapper_argv.begin(), wrapper_argv.end());
begin_args_ += wrapper_argv.size(); begin_args_ += wrapper_argv.size();
......
...@@ -406,4 +406,35 @@ TEST(CommandLineTest, Copy) { ...@@ -406,4 +406,35 @@ TEST(CommandLineTest, Copy) {
EXPECT_TRUE(assigned.HasSwitch(pair.first)); EXPECT_TRUE(assigned.HasSwitch(pair.first));
} }
TEST(CommandLineTest, PrependSimpleWrapper) {
CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
cl.AppendSwitch("a");
cl.AppendSwitch("b");
cl.PrependWrapper(FILE_PATH_LITERAL("wrapper --foo --bar"));
EXPECT_EQ(6u, cl.argv().size());
EXPECT_EQ(FILE_PATH_LITERAL("wrapper"), cl.argv()[0]);
EXPECT_EQ(FILE_PATH_LITERAL("--foo"), cl.argv()[1]);
EXPECT_EQ(FILE_PATH_LITERAL("--bar"), cl.argv()[2]);
EXPECT_EQ(FILE_PATH_LITERAL("Program"), cl.argv()[3]);
EXPECT_EQ(FILE_PATH_LITERAL("--a"), cl.argv()[4]);
EXPECT_EQ(FILE_PATH_LITERAL("--b"), cl.argv()[5]);
}
TEST(CommandLineTest, PrependComplexWrapper) {
CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
cl.AppendSwitch("a");
cl.AppendSwitch("b");
cl.PrependWrapper(
FILE_PATH_LITERAL("wrapper --foo='hello world' --bar=\"let's go\""));
EXPECT_EQ(6u, cl.argv().size());
EXPECT_EQ(FILE_PATH_LITERAL("wrapper"), cl.argv()[0]);
EXPECT_EQ(FILE_PATH_LITERAL("--foo='hello world'"), cl.argv()[1]);
EXPECT_EQ(FILE_PATH_LITERAL("--bar=\"let's go\""), cl.argv()[2]);
EXPECT_EQ(FILE_PATH_LITERAL("Program"), cl.argv()[3]);
EXPECT_EQ(FILE_PATH_LITERAL("--a"), cl.argv()[4]);
EXPECT_EQ(FILE_PATH_LITERAL("--b"), cl.argv()[5]);
}
} // namespace base } // namespace base
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment