mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-10 01:17:44 +03:00
strv: rework strv_split_quoted() to use unquote_first_word()
This should make the unquoting scheme a bit less naive.
This commit is contained in:
parent
27e9c5af81
commit
f88e6be5ee
@ -149,7 +149,7 @@ static int spawn_getter(const char *getter, const char *url) {
|
||||
_cleanup_strv_free_ char **words = NULL;
|
||||
|
||||
assert(getter);
|
||||
r = strv_split_quoted(&words, getter);
|
||||
r = strv_split_quoted(&words, getter, false);
|
||||
if (r < 0) {
|
||||
log_error("Failed to split getter option: %s", strerror(-r));
|
||||
return r;
|
||||
|
@ -224,7 +224,7 @@ static int x11_read_data(Context *c) {
|
||||
if (in_section && first_word(l, "Option")) {
|
||||
_cleanup_strv_free_ char **a = NULL;
|
||||
|
||||
r = strv_split_quoted(&a, l);
|
||||
r = strv_split_quoted(&a, l, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -247,7 +247,7 @@ static int x11_read_data(Context *c) {
|
||||
} else if (!in_section && first_word(l, "Section")) {
|
||||
_cleanup_strv_free_ char **a = NULL;
|
||||
|
||||
r = strv_split_quoted(&a, l);
|
||||
r = strv_split_quoted(&a, l, false);
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -533,7 +533,7 @@ static int read_next_mapping(FILE *f, unsigned *n, char ***a) {
|
||||
if (l[0] == 0 || l[0] == '#')
|
||||
continue;
|
||||
|
||||
r = strv_split_quoted(&b, l);
|
||||
r = strv_split_quoted(&b, l, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -248,40 +248,6 @@ char **strv_split(const char *s, const char *separator) {
|
||||
return r;
|
||||
}
|
||||
|
||||
int strv_split_quoted(char ***t, const char *s) {
|
||||
const char *word, *state;
|
||||
size_t l;
|
||||
unsigned n, i;
|
||||
char **r;
|
||||
|
||||
assert(s);
|
||||
|
||||
n = 0;
|
||||
FOREACH_WORD_QUOTED(word, l, s, state)
|
||||
n++;
|
||||
if (!isempty(state))
|
||||
/* bad syntax */
|
||||
return -EINVAL;
|
||||
|
||||
r = new(char*, n+1);
|
||||
if (!r)
|
||||
return -ENOMEM;
|
||||
|
||||
i = 0;
|
||||
FOREACH_WORD_QUOTED(word, l, s, state) {
|
||||
r[i] = cunescape_length(word, l);
|
||||
if (!r[i]) {
|
||||
strv_free(r);
|
||||
return -ENOMEM;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
r[i] = NULL;
|
||||
*t = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char **strv_split_newlines(const char *s) {
|
||||
char **l;
|
||||
unsigned n;
|
||||
@ -307,6 +273,41 @@ char **strv_split_newlines(const char *s) {
|
||||
return l;
|
||||
}
|
||||
|
||||
int strv_split_quoted(char ***t, const char *s, bool relax) {
|
||||
size_t n = 0, allocated = 0;
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
int r;
|
||||
|
||||
assert(t);
|
||||
assert(s);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
|
||||
r = unquote_first_word(&s, &word, relax);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (!GREEDY_REALLOC(l, allocated, n + 2))
|
||||
return -ENOMEM;
|
||||
|
||||
l[n++] = word;
|
||||
word = NULL;
|
||||
|
||||
l[n] = NULL;
|
||||
}
|
||||
|
||||
if (!l)
|
||||
l = new0(char*, 1);
|
||||
|
||||
*t = l;
|
||||
l = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *strv_join(char **l, const char *separator) {
|
||||
char *r, *e;
|
||||
char **s;
|
||||
|
@ -63,9 +63,10 @@ static inline bool strv_isempty(char * const *l) {
|
||||
}
|
||||
|
||||
char **strv_split(const char *s, const char *separator);
|
||||
int strv_split_quoted(char ***t, const char *s);
|
||||
char **strv_split_newlines(const char *s);
|
||||
|
||||
int strv_split_quoted(char ***t, const char *s, bool relax);
|
||||
|
||||
char *strv_join(char **l, const char *separator);
|
||||
char *strv_join_quoted(char **l);
|
||||
|
||||
|
@ -3292,7 +3292,7 @@ char **replace_env_argv(char **argv, char **env) {
|
||||
if (e) {
|
||||
int r;
|
||||
|
||||
r = strv_split_quoted(&m, e);
|
||||
r = strv_split_quoted(&m, e, true);
|
||||
if (r < 0) {
|
||||
ret[k] = NULL;
|
||||
strv_free(ret);
|
||||
|
@ -165,7 +165,7 @@ static void test_strv_quote_unquote(const char* const *split, const char *quoted
|
||||
assert_se(p);
|
||||
assert_se(streq(p, quoted));
|
||||
|
||||
r = strv_split_quoted(&s, quoted);
|
||||
r = strv_split_quoted(&s, quoted, false);
|
||||
assert_se(r == 0);
|
||||
assert_se(s);
|
||||
STRV_FOREACH(t, s) {
|
||||
@ -182,7 +182,7 @@ static void test_strv_unquote(const char *quoted, const char **list) {
|
||||
char **t;
|
||||
int r;
|
||||
|
||||
r = strv_split_quoted(&s, quoted);
|
||||
r = strv_split_quoted(&s, quoted, false);
|
||||
assert_se(r == 0);
|
||||
assert_se(s);
|
||||
j = strv_join(s, " | ");
|
||||
@ -199,7 +199,7 @@ static void test_invalid_unquote(const char *quoted) {
|
||||
char **s = NULL;
|
||||
int r;
|
||||
|
||||
r = strv_split_quoted(&s, quoted);
|
||||
r = strv_split_quoted(&s, quoted, false);
|
||||
assert_se(s == NULL);
|
||||
assert_se(r == -EINVAL);
|
||||
}
|
||||
@ -482,12 +482,12 @@ int main(int argc, char *argv[]) {
|
||||
test_strv_unquote(" \"x'\" ", (const char*[]) { "x'", NULL });
|
||||
test_strv_unquote("a '--b=c \"d e\"'", (const char*[]) { "a", "--b=c \"d e\"", NULL });
|
||||
|
||||
test_invalid_unquote("a --b='c \"d e\"'");
|
||||
test_invalid_unquote("a --b='c \"d e\" '");
|
||||
test_invalid_unquote("a --b='c \"d e\"''");
|
||||
test_invalid_unquote("a --b='c \"d e\" '\"");
|
||||
test_invalid_unquote("a --b='c \"d e\"garbage");
|
||||
test_invalid_unquote("'");
|
||||
test_invalid_unquote("\"");
|
||||
test_invalid_unquote("'x'y");
|
||||
test_invalid_unquote("'x'y'g");
|
||||
|
||||
test_strv_split();
|
||||
test_strv_split_newlines();
|
||||
|
Loading…
Reference in New Issue
Block a user