]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #15309 from poettering/strv-split
authorEvgeny Vereshchagin <evvers@ya.ru>
Fri, 3 Apr 2020 03:37:54 +0000 (06:37 +0300)
committerGitHub <noreply@github.com>
Fri, 3 Apr 2020 03:37:54 +0000 (06:37 +0300)
remove dead-lock in strv_split()

TODO
src/basic/string-util.c
src/basic/string-util.h
src/test/test-strv.c

diff --git a/TODO b/TODO
index a31a9405cdc0e3e6e795e9e5ce7566b1cc1daa8b..ef204dfed05ea3607ca17e0dd79f9a8d3aff1c77 100644 (file)
--- a/TODO
+++ b/TODO
@@ -117,7 +117,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
 
@@ -864,6 +865,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
index 8f812d7cbe07ebdb31e3dd581796c8144327b68b..9983aa826e69cc68dfdfa1fc952bf52c1ab340ab 100644 (file)
@@ -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,50 +122,62 @@ 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. */
-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'};
-
-                *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 (FLAGS_SET(flags, SPLIT_QUOTES)) {
+
+                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 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 + 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;
         } else {
                 *l = strcspn(current, separator);
                 *state = current + *l;
index f98fbddddadd411afdecaa5d2fed636c8ffb6dd9..2a344b996f9953fd76b890a29ff032c243fc1c95 100644 (file)
@@ -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)
 
index 68c128cf80d1370f568cbc8a484d39dcc7b5ef0e..5473e983bd843ad11c2880cf614e51837ad331a6 100644 (file)
@@ -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) {