From 77b19caf6b2e89256937698103d32c9884a2bf6c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Apr 2020 16:00:06 +0200 Subject: [PATCH 1/4] update TODO --- TODO | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/TODO b/TODO index e944245a57..cd31516793 100644 --- a/TODO +++ b/TODO @@ -113,7 +113,8 @@ Features: * systemd-repart: allow config of partition uuid -* userdb: allow username prefix searches in varlink API +* userdb: allow username prefix searches in varlink API, allow realname and + realname substr searches in varlink API * userdb: allow existence checks @@ -860,6 +861,7 @@ Features: make assumptions about their slice anymore. - follow PropertiesChanged state more closely, to deal with quick logouts and relogins + - (optionally?) spawn seat-manager@$SEAT.service whenever a seat shows up that as CanGraphical set * journal: - consider introducing implicit _TTY= + _PPID= + _EUID= + _EGID= + _FSUID= + _FSGID= fields From 5fed82c642963f58de96ffc112935ced2d2a3ade Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Apr 2020 16:00:55 +0200 Subject: [PATCH 2/4] string-util: some minor coding style updates --- src/basic/string-util.c | 65 ++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/src/basic/string-util.c b/src/basic/string-util.c index 8f812d7cbe..2eb84babd8 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -127,45 +127,58 @@ static size_t strcspn_escaped(const char *s, const char *reject) { } /* Split a string into words. */ -const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags) { +const char* split( + const char **state, + size_t *l, + const char *separator, + SplitFlags flags) { + const char *current; + assert(state); + assert(l); + + if (!separator) + separator = WHITESPACE; + current = *state; - if (!*current) { - assert(**state == '\0'); + if (*current == '\0') /* already at the end? */ return NULL; - } - current += strspn(current, separator); - if (!*current) { + current += strspn(current, separator); /* skip leading separators */ + if (*current == '\0') { /* at the end now? */ *state = current; return NULL; } - if (flags & SPLIT_QUOTES && strchr("\'\"", *current)) { - char quotechars[2] = {*current, '\0'}; + if (FLAGS_SET(flags, SPLIT_QUOTES)) { - *l = strcspn_escaped(current + 1, quotechars); - if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] || - (current[*l + 2] && !strchr(separator, current[*l + 2]))) { - /* right quote missing or garbage at the end */ - if (flags & SPLIT_RELAX) { - *state = current + *l + 1 + (current[*l + 1] != '\0'); - return current + 1; + if (strchr(QUOTES, *current)) { + /* We are looking at a quote */ + *l = strcspn_escaped(current + 1, CHAR_TO_STR(*current)); + if (current[*l + 1] != *current || + (current[*l + 2] != 0 && !strchr(separator, current[*l + 2]))) { + /* right quote missing or garbage at the end */ + if (FLAGS_SET(flags, SPLIT_RELAX)) { + *state = current + *l + 1 + (current[*l + 1] != '\0'); + return current + 1; + } + *state = current; + return NULL; } - *state = current; - return NULL; + *state = current++ + *l + 2; + + } else { + /* We are looking at a something that is not a quote */ + *l = strcspn_escaped(current, separator); + if (current[*l] && !strchr(separator, current[*l]) && !FLAGS_SET(flags, SPLIT_RELAX)) { + /* unfinished escape */ + *state = current; + return NULL; + } + *state = current + *l; } - *state = current++ + *l + 2; - } else if (flags & SPLIT_QUOTES) { - *l = strcspn_escaped(current, separator); - if (current[*l] && !strchr(separator, current[*l]) && !(flags & SPLIT_RELAX)) { - /* unfinished escape */ - *state = current; - return NULL; - } - *state = current + *l; } else { *l = strcspn(current, separator); *state = current + *l; From 29965a2a6e22c9f369e70cffd9ff780d1c1d31a1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Apr 2020 16:36:33 +0200 Subject: [PATCH 3/4] string-util: make sure we eat even half complete words in split() split() and FOREACH_WORD really should die, and everything be moved to extract_first_word() and friends, but let's at least make sure that for the remaining code using it we can't deadlock by not progressing in the word iteration. Fixes: #15305 --- src/basic/string-util.c | 5 ++--- src/test/test-strv.c | 6 ++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/basic/string-util.c b/src/basic/string-util.c index 2eb84babd8..9983aa826e 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -113,7 +113,7 @@ static size_t strcspn_escaped(const char *s, const char *reject) { bool escaped = false; int n; - for (n=0; s[n]; n++) { + for (n = 0; s[n] != '\0'; n++) { if (escaped) escaped = false; else if (s[n] == '\\') @@ -122,8 +122,7 @@ static size_t strcspn_escaped(const char *s, const char *reject) { break; } - /* if s ends in \, return index of previous char */ - return n - escaped; + return n; } /* Split a string into words. */ diff --git a/src/test/test-strv.c b/src/test/test-strv.c index 68c128cf80..5473e983bd 100644 --- a/src/test/test-strv.c +++ b/src/test/test-strv.c @@ -307,6 +307,12 @@ static void test_strv_split(void) { l = strv_split_full(" 'one' \" two\t three \"' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX); assert_se(l); assert_se(strv_equal(l, (char**) input_table_quoted)); + + strv_free_erase(l); + + l = strv_split_full("\\", NULL, SPLIT_QUOTES | SPLIT_RELAX); + assert_se(l); + assert_se(strv_equal(l, STRV_MAKE("\\"))); } static void test_strv_split_empty(void) { From 82aa14e2a334976adf6bec6c6c08982c57d2a048 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Apr 2020 16:38:27 +0200 Subject: [PATCH 4/4] string-util: make clear that split() + FOREACH_WORD() should die --- src/basic/string-util.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/basic/string-util.h b/src/basic/string-util.h index f98fbdddda..2a344b996f 100644 --- a/src/basic/string-util.h +++ b/src/basic/string-util.h @@ -112,8 +112,10 @@ typedef enum SplitFlags { SPLIT_RELAX = 0x01 << 1, } SplitFlags; +/* Smelly. Do not use this anymore. Use extract_first_word() instead! */ const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags); +/* Similar, don't use this anymore */ #define FOREACH_WORD(word, length, s, state) \ _FOREACH_WORD(word, length, s, WHITESPACE, 0, state)