summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2017-03-19 13:53:33 +0100
committerDavid Kalnischkies <david@kalnischkies.de>2017-03-19 14:32:59 +0100
commit2ce15bdeac6ee93faefd4b42b57f035bef80c567 (patch)
tree630828a5cab9f1747a54508e5fe44d00e4ff9ee7
parentc8ecf96594c7fad8781775590dafc302b49fe6a8 (diff)
Fix and avoid quoting in CommandLine::AsString
In the intended usecase where this serves as a hack there is no problem with double/single quotes being present as we write it to a log file only, but nowadays our calling of apt-key produces a temporary config file containing this "setting" as well and suddently quoting is important as the config file syntax is allergic to it. So the fix is to ignore all quoting whatsoever in the input and just quote (with singles) the option values with spaces. That gives us 99% of the time the correct result and the 1% where the quote is an integral element of the option … doesn't exist – or has bigger problems than a log file not containing the quote. Same goes for newlines in values. LP: #1672710
-rw-r--r--apt-pkg/contrib/cmndline.cc14
-rw-r--r--test/libapt/commandline_test.cc10
2 files changed, 19 insertions, 5 deletions
diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc
index c8a6e2787..029ec3060 100644
--- a/apt-pkg/contrib/cmndline.cc
+++ b/apt-pkg/contrib/cmndline.cc
@@ -402,21 +402,27 @@ void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * co
bool closeQuote = false;
for (unsigned int i = 0; i < argc && length < sizeof(cmdline); ++i, ++length)
{
- for (unsigned int j = 0; argv[i][j] != '\0' && length < sizeof(cmdline)-1; ++j, ++length)
+ for (unsigned int j = 0; argv[i][j] != '\0' && length < sizeof(cmdline)-2; ++j)
{
- cmdline[length] = argv[i][j];
+ // we can't really sensibly deal with quoting so skip it
+ if (strchr("\"\'\r\n", argv[i][j]) != nullptr)
+ continue;
+ cmdline[length++] = argv[i][j];
if (lastWasOption == true && argv[i][j] == '=')
{
// That is possibly an option: Quote it if it includes spaces,
// the benefit is that this will eliminate also most false positives
const char* c = strchr(&argv[i][j+1], ' ');
if (c == NULL) continue;
- cmdline[++length] = '"';
+ cmdline[length++] = '\'';
closeQuote = true;
}
}
if (closeQuote == true)
- cmdline[length++] = '"';
+ {
+ cmdline[length++] = '\'';
+ closeQuote = false;
+ }
// Problem: detects also --hello
if (cmdline[length-1] == 'o')
lastWasOption = true;
diff --git a/test/libapt/commandline_test.cc b/test/libapt/commandline_test.cc
index 97725c854..1dc9c6946 100644
--- a/test/libapt/commandline_test.cc
+++ b/test/libapt/commandline_test.cc
@@ -24,8 +24,16 @@ TEST(CommandLineTest,SaveInConfig)
"apt-get", "install", "-sf");
APT_EXPECT_CMD("apt-cache -s apt -so Debug::test=Test",
"apt-cache", "-s", "apt", "-so", "Debug::test=Test");
- APT_EXPECT_CMD("apt-cache -s apt -so Debug::test=\"Das ist ein Test\"",
+ APT_EXPECT_CMD("apt-cache -s apt -so Debug::test='Das ist ein Test'",
"apt-cache", "-s", "apt", "-so", "Debug::test=Das ist ein Test");
+ APT_EXPECT_CMD("apt-cache -s apt -so Debug::test='Das ist ein Test'",
+ "apt-cache", "-s", "apt", "-so", "Debug::test=\"Das ist ein Test\"");
+ APT_EXPECT_CMD("apt-cache -s apt -so Debug::test='Das ist ein Test' foo",
+ "apt-cache", "-s", "apt", "-so", "\"Debug::test=Das ist ein Test\"", "foo");
+ APT_EXPECT_CMD("apt-cache -s apt -so Debug::test='Das ist ein Test' foo",
+ "apt-cache", "-s", "apt", "-so", "\'Debug::test=Das ist ein Test\'", "foo");
+ APT_EXPECT_CMD("apt-cache -s apt -so Debug::test='That is crazy!' foo",
+ "apt-cache", "-s", "apt", "-so", "\'Debug::test=That \ris\n crazy!\'", "foo");
APT_EXPECT_CMD("apt-cache -s apt --hallo test=1.0",
"apt-cache", "-s", "apt", "--hallo", "test=1.0");
#undef APT_EXPECT_CMD