mirror of
https://github.com/clearlinux/systemd-stable.git
synced 2026-09-08 14:41:51 +00:00
Treat a trailing backslash as an error
Commita2a5291b3fchanged the parser to reject unfinished quoted strings. Unfortunately it introduced an error where a trailing backslash would case an infinite loop. Of course this must fixed, but the question is what to to instead. Allowing trailing backslashes and treating them as normal characters would be one option, but this seems suboptimal. First, there would be inconsistency between handling of quoting and of backslashes. Second, a trailing backslash is most likely an error, at it seems better to point it out to the user than to try to continue. Updated rules: ExecStart=/bin/echo \\ → OK, prints a backslash ExecStart=/bin/echo \ → error ExecStart=/bin/echo "x → error ExecStart=/bin/echo "x"y → error (cherry picked from commitba774317ac) Conflicts: src/test/test-strv.c
This commit is contained in:
+7
-1
@@ -418,7 +418,7 @@ int safe_atod(const char *s, double *ret_d) {
|
||||
|
||||
static size_t strcspn_escaped(const char *s, const char *reject) {
|
||||
bool escaped = false;
|
||||
size_t n;
|
||||
int n;
|
||||
|
||||
for (n=0; s[n]; n++) {
|
||||
if (escaped)
|
||||
@@ -428,6 +428,7 @@ static size_t strcspn_escaped(const char *s, const char *reject) {
|
||||
else if (strchr(reject, s[n]))
|
||||
break;
|
||||
}
|
||||
|
||||
/* if s ends in \, return index of previous char */
|
||||
return n - escaped;
|
||||
}
|
||||
@@ -463,6 +464,11 @@ const char* split(const char **state, size_t *l, const char *separator, bool quo
|
||||
*state = current++ + *l + 2;
|
||||
} else if (quoted) {
|
||||
*l = strcspn_escaped(current, separator);
|
||||
if (current[*l] && !strchr(separator, current[*l])) {
|
||||
/* unfinished escape */
|
||||
*state = current;
|
||||
return NULL;
|
||||
}
|
||||
*state = current + *l;
|
||||
} else {
|
||||
*l = strcspn(current, separator);
|
||||
|
||||
@@ -446,6 +446,11 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
test_invalid_unquote("a --b='c \"d e\"'");
|
||||
test_invalid_unquote("a --b='c \"d e\" '");
|
||||
|
||||
/* trailing backslashes */
|
||||
test_strv_unquote(" x\\\\", STRV_MAKE("x\\"));
|
||||
test_invalid_unquote(" x\\");
|
||||
|
||||
test_invalid_unquote("a --b='c \"d e\"garbage");
|
||||
test_invalid_unquote("'");
|
||||
test_invalid_unquote("\"");
|
||||
|
||||
+30
-19
@@ -405,28 +405,12 @@ static void test_foreach_word(void) {
|
||||
assert_se(strneq(expected[i++], word, l));
|
||||
}
|
||||
|
||||
static void test_foreach_word_quoted(void) {
|
||||
static void check(const char *test, char** expected, bool trailing) {
|
||||
const char *word, *state;
|
||||
size_t l;
|
||||
int i = 0;
|
||||
const char test[] = "test a b c 'd' e '' '' hhh '' '' \"a b c\"";
|
||||
const char * const expected[] = {
|
||||
"test",
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"d",
|
||||
"e",
|
||||
"",
|
||||
"",
|
||||
"hhh",
|
||||
"",
|
||||
"",
|
||||
"a b c",
|
||||
NULL
|
||||
};
|
||||
|
||||
printf("<%s>\n", test);
|
||||
printf("<<<%s>>>\n", test);
|
||||
FOREACH_WORD_QUOTED(word, l, test, state) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
|
||||
@@ -434,7 +418,34 @@ static void test_foreach_word_quoted(void) {
|
||||
assert_se(strneq(expected[i++], word, l));
|
||||
printf("<%s>\n", t);
|
||||
}
|
||||
assert_se(isempty(state));
|
||||
printf("<<<%s>>>\n", state);
|
||||
assert(expected[i] == NULL);
|
||||
assert_se(isempty(state) == !trailing);
|
||||
}
|
||||
|
||||
static void test_foreach_word_quoted(void) {
|
||||
check("test a b c 'd' e '' '' hhh '' '' \"a b c\"",
|
||||
STRV_MAKE("test",
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"d",
|
||||
"e",
|
||||
"",
|
||||
"",
|
||||
"hhh",
|
||||
"",
|
||||
"",
|
||||
"a b c"),
|
||||
false);
|
||||
|
||||
check("test \"xxx",
|
||||
STRV_MAKE("test"),
|
||||
true);
|
||||
|
||||
check("test\\",
|
||||
STRV_MAKE_EMPTY,
|
||||
true);
|
||||
}
|
||||
|
||||
static void test_default_term_for_tty(void) {
|
||||
|
||||
Reference in New Issue
Block a user