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