Zbigniew Jędrzejewski-Szmek ef7b48
From e7a90c1117e4d37be191a6567b405d7908a30434 Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek ef7b48
From: Martin Pitt <martin.pitt@ubuntu.com>
Zbigniew Jędrzejewski-Szmek ef7b48
Date: Wed, 22 Apr 2015 23:09:43 +0100
Zbigniew Jędrzejewski-Szmek ef7b48
Subject: [PATCH] util: Fix assertion in split() on missing '
Zbigniew Jędrzejewski-Szmek ef7b48
Zbigniew Jędrzejewski-Szmek ef7b48
When parsing a unit with a trailing slash after an escaped line break, like
Zbigniew Jędrzejewski-Szmek ef7b48
Zbigniew Jędrzejewski-Szmek ef7b48
  ExecStart=/bin/echo 'foo \
Zbigniew Jędrzejewski-Szmek ef7b48
    bar'
Zbigniew Jędrzejewski-Szmek ef7b48
Zbigniew Jędrzejewski-Szmek ef7b48
the split() function (through config_parse()) asserted and crashed pid 1:
Zbigniew Jędrzejewski-Szmek ef7b48
Zbigniew Jędrzejewski-Szmek ef7b48
  Assertion 'current[*l + 1] == quotechars[0]' failed at ../src/shared/util.c:583, function split(). Aborting.
Zbigniew Jędrzejewski-Szmek ef7b48
Zbigniew Jędrzejewski-Szmek ef7b48
Fix this by returning an error in this case ("trailing garbage").
Zbigniew Jędrzejewski-Szmek ef7b48
Zbigniew Jędrzejewski-Szmek ef7b48
Add corresponding test case. Also fix the missing "unit" argument of
Zbigniew Jędrzejewski-Szmek ef7b48
config_parse_exec() in the comment.
Zbigniew Jędrzejewski-Szmek ef7b48
Zbigniew Jędrzejewski-Szmek ef7b48
https://launchpad.net/bugs/1447243
Zbigniew Jędrzejewski-Szmek ef7b48
(cherry picked from commit 470dca63cd2b1579f45f72b6b9777494abeff105)
Zbigniew Jędrzejewski-Szmek ef7b48
---
Zbigniew Jędrzejewski-Szmek ef7b48
 src/shared/util.c         |  3 +--
Zbigniew Jędrzejewski-Szmek ef7b48
 src/test/test-unit-file.c | 15 +++++++++++++++
Zbigniew Jędrzejewski-Szmek ef7b48
 2 files changed, 16 insertions(+), 2 deletions(-)
Zbigniew Jędrzejewski-Szmek ef7b48
Zbigniew Jędrzejewski-Szmek ef7b48
diff --git a/src/shared/util.c b/src/shared/util.c
Zbigniew Jędrzejewski-Szmek ef7b48
index 1e1bf944f2..649344d88f 100644
Zbigniew Jędrzejewski-Szmek ef7b48
--- a/src/shared/util.c
Zbigniew Jędrzejewski-Szmek ef7b48
+++ b/src/shared/util.c
Zbigniew Jędrzejewski-Szmek ef7b48
@@ -571,13 +571,12 @@ const char* split(const char **state, size_t *l, const char *separator, bool quo
Zbigniew Jędrzejewski-Szmek ef7b48
                 char quotechars[2] = {*current, '\0'};
Zbigniew Jędrzejewski-Szmek ef7b48
 
Zbigniew Jędrzejewski-Szmek ef7b48
                 *l = strcspn_escaped(current + 1, quotechars);
Zbigniew Jędrzejewski-Szmek ef7b48
-                if (current[*l + 1] == '\0' ||
Zbigniew Jędrzejewski-Szmek ef7b48
+                if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
Zbigniew Jędrzejewski-Szmek ef7b48
                     (current[*l + 2] && !strchr(separator, current[*l + 2]))) {
Zbigniew Jędrzejewski-Szmek ef7b48
                         /* right quote missing or garbage at the end */
Zbigniew Jędrzejewski-Szmek ef7b48
                         *state = current;
Zbigniew Jędrzejewski-Szmek ef7b48
                         return NULL;
Zbigniew Jędrzejewski-Szmek ef7b48
                 }
Zbigniew Jędrzejewski-Szmek ef7b48
-                assert(current[*l + 1] == quotechars[0]);
Zbigniew Jędrzejewski-Szmek ef7b48
                 *state = current++ + *l + 2;
Zbigniew Jędrzejewski-Szmek ef7b48
         } else if (quoted) {
Zbigniew Jędrzejewski-Szmek ef7b48
                 *l = strcspn_escaped(current, separator);
Zbigniew Jędrzejewski-Szmek ef7b48
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
Zbigniew Jędrzejewski-Szmek ef7b48
index e517f571d6..9f3e3a227e 100644
Zbigniew Jędrzejewski-Szmek ef7b48
--- a/src/test/test-unit-file.c
Zbigniew Jędrzejewski-Szmek ef7b48
+++ b/src/test/test-unit-file.c
Zbigniew Jędrzejewski-Szmek ef7b48
@@ -92,6 +92,7 @@ static void check_execcommand(ExecCommand *c,
Zbigniew Jędrzejewski-Szmek ef7b48
 
Zbigniew Jędrzejewski-Szmek ef7b48
 static void test_config_parse_exec(void) {
Zbigniew Jędrzejewski-Szmek ef7b48
         /* int config_parse_exec(
Zbigniew Jędrzejewski-Szmek ef7b48
+                 const char *unit,
Zbigniew Jędrzejewski-Szmek ef7b48
                  const char *filename,
Zbigniew Jędrzejewski-Szmek ef7b48
                  unsigned line,
Zbigniew Jędrzejewski-Szmek ef7b48
                  const char *section,
Zbigniew Jędrzejewski-Szmek ef7b48
@@ -303,6 +304,20 @@ static void test_config_parse_exec(void) {
Zbigniew Jędrzejewski-Szmek ef7b48
         assert_se(r == 0);
Zbigniew Jędrzejewski-Szmek ef7b48
         assert_se(c1->command_next == NULL);
Zbigniew Jędrzejewski-Szmek ef7b48
 
Zbigniew Jędrzejewski-Szmek ef7b48
+        log_info("/* missing ending ' */");
Zbigniew Jędrzejewski-Szmek ef7b48
+        r = config_parse_exec(NULL, "fake", 4, "section", 1,
Zbigniew Jędrzejewski-Szmek ef7b48
+                              "LValue", 0, "/path 'foo",
Zbigniew Jędrzejewski-Szmek ef7b48
+                              &c, NULL);
Zbigniew Jędrzejewski-Szmek ef7b48
+        assert_se(r == 0);
Zbigniew Jędrzejewski-Szmek ef7b48
+        assert_se(c1->command_next == NULL);
Zbigniew Jędrzejewski-Szmek ef7b48
+
Zbigniew Jędrzejewski-Szmek ef7b48
+        log_info("/* missing ending ' with trailing backslash */");
Zbigniew Jędrzejewski-Szmek ef7b48
+        r = config_parse_exec(NULL, "fake", 4, "section", 1,
Zbigniew Jędrzejewski-Szmek ef7b48
+                              "LValue", 0, "/path 'foo\\",
Zbigniew Jędrzejewski-Szmek ef7b48
+                              &c, NULL);
Zbigniew Jędrzejewski-Szmek ef7b48
+        assert_se(r == 0);
Zbigniew Jędrzejewski-Szmek ef7b48
+        assert_se(c1->command_next == NULL);
Zbigniew Jędrzejewski-Szmek ef7b48
+
Zbigniew Jędrzejewski-Szmek ef7b48
         exec_command_free_list(c);
Zbigniew Jędrzejewski-Szmek ef7b48
 }
Zbigniew Jędrzejewski-Szmek ef7b48