Reject invalid quoted strings

String which ended in an unfinished quote were accepted, potentially
with bad memory accesses.

Reject anything which ends in a unfished quote, or contains
non-whitespace characters right after the closing quote.

_FOREACH_WORD now returns the invalid character in *state. But this return
value is not checked anywhere yet.

Also, make 'word' and 'state' variables const pointers, and rename 'w'
to 'word' in various places. Things are easier to read if the same name
is used consistently.

mbiebl_> am I correct that something like this doesn't work
mbiebl_> ExecStart=/usr/bin/encfs --extpass='/bin/systemd-ask-passwd "Unlock EncFS"'
mbiebl_> systemd seems to strip of the quotes
mbiebl_> systemctl status shows
mbiebl_> ExecStart=/usr/bin/encfs --extpass='/bin/systemd-ask-password Unlock EncFS  $RootDir $MountPoint
mbiebl_> which is pretty weird
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2014-07-29 22:01:36 -04:00
parent 73381fcf54
commit a2a5291b3f
33 changed files with 268 additions and 242 deletions

View File

@ -220,7 +220,7 @@ static int device_make_description(Unit *u, struct udev_device *dev, const char
static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
const char *wants;
char *state, *w;
const char *word, *state;
size_t l;
int r;
@ -234,11 +234,11 @@ static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
if (!wants)
return 0;
FOREACH_WORD_QUOTED(w, l, wants, state) {
FOREACH_WORD_QUOTED(word, l, wants, state) {
_cleanup_free_ char *n = NULL;
char e[l+1];
memcpy(e, w, l);
memcpy(e, word, l);
e[l] = 0;
n = unit_name_mangle(e, MANGLE_NOGLOB);
@ -393,13 +393,13 @@ static int device_process_new_device(Manager *m, struct udev_device *dev) {
* aliases */
alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS");
if (alias) {
char *state, *w;
const char *word, *state;
size_t l;
FOREACH_WORD_QUOTED(w, l, alias, state) {
FOREACH_WORD_QUOTED(word, l, alias, state) {
char e[l+1];
memcpy(e, w, l);
memcpy(e, word, l);
e[l] = 0;
if (path_is_absolute(e))

View File

@ -97,18 +97,18 @@ int config_parse_unit_deps(const char* unit,
UnitDependency d = ltype;
Unit *u = userdata;
char *w, *state;
const char *word, *state;
size_t l;
assert(filename);
assert(lvalue);
assert(rvalue);
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
_cleanup_free_ char *t = NULL, *k = NULL;
int r;
t = strndup(w, l);
t = strndup(word, l);
if (!t)
return log_oom();
@ -227,7 +227,8 @@ int config_parse_unit_path_strv_printf(
void *data,
void *userdata) {
char *w, *state, ***x = data;
char ***x = data;
const char *word, *state;
Unit *u = userdata;
size_t l;
int r;
@ -237,11 +238,11 @@ int config_parse_unit_path_strv_printf(
assert(rvalue);
assert(u);
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
_cleanup_free_ char *k = NULL;
char t[l+1];
memcpy(t, w, l);
memcpy(t, word, l);
t[l] = 0;
r = unit_full_printf(u, t, &k);
@ -533,9 +534,8 @@ int config_parse_exec(const char *unit,
* overriding of argv[0]. */
for (;;) {
int i;
char *w;
const char *word, *state;
size_t l;
char *state;
bool honour_argv0 = false, ignore = false;
path = NULL;
@ -566,8 +566,8 @@ int config_parse_exec(const char *unit,
}
k = 0;
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
if (strneq(w, ";", MAX(l, 1U)))
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
if (strneq(word, ";", MAX(l, 1U)))
break;
k++;
@ -578,16 +578,16 @@ int config_parse_exec(const char *unit,
return log_oom();
k = 0;
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
if (strneq(w, ";", MAX(l, 1U)))
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
if (strneq(word, ";", MAX(l, 1U)))
break;
else if (strneq(w, "\\;", MAX(l, 1U)))
w ++;
else if (strneq(word, "\\;", MAX(l, 1U)))
word ++;
if (honour_argv0 && w == rvalue) {
if (honour_argv0 && word == rvalue) {
assert(!path);
path = strndup(w, l);
path = strndup(word, l);
if (!path) {
r = log_oom();
goto fail;
@ -602,7 +602,7 @@ int config_parse_exec(const char *unit,
} else {
char *c;
c = n[k++] = cunescape_length(w, l);
c = n[k++] = cunescape_length(word, l);
if (!c) {
r = log_oom();
goto fail;
@ -854,9 +854,8 @@ int config_parse_exec_cpu_affinity(const char *unit,
void *userdata) {
ExecContext *c = data;
char *w;
const char *word, *state;
size_t l;
char *state;
assert(filename);
assert(lvalue);
@ -871,12 +870,12 @@ int config_parse_exec_cpu_affinity(const char *unit,
return 0;
}
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
_cleanup_free_ char *t = NULL;
int r;
unsigned cpu;
t = strndup(w, l);
t = strndup(word, l);
if (!t)
return log_oom();
@ -945,9 +944,8 @@ int config_parse_exec_secure_bits(const char *unit,
void *userdata) {
ExecContext *c = data;
char *w;
size_t l;
char *state;
const char *word, *state;
assert(filename);
assert(lvalue);
@ -960,18 +958,18 @@ int config_parse_exec_secure_bits(const char *unit,
return 0;
}
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
if (first_word(w, "keep-caps"))
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
if (first_word(word, "keep-caps"))
c->secure_bits |= 1<<SECURE_KEEP_CAPS;
else if (first_word(w, "keep-caps-locked"))
else if (first_word(word, "keep-caps-locked"))
c->secure_bits |= 1<<SECURE_KEEP_CAPS_LOCKED;
else if (first_word(w, "no-setuid-fixup"))
else if (first_word(word, "no-setuid-fixup"))
c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP;
else if (first_word(w, "no-setuid-fixup-locked"))
else if (first_word(word, "no-setuid-fixup-locked"))
c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP_LOCKED;
else if (first_word(w, "noroot"))
else if (first_word(word, "noroot"))
c->secure_bits |= 1<<SECURE_NOROOT;
else if (first_word(w, "noroot-locked"))
else if (first_word(word, "noroot-locked"))
c->secure_bits |= 1<<SECURE_NOROOT_LOCKED;
else {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
@ -995,9 +993,8 @@ int config_parse_bounding_set(const char *unit,
void *userdata) {
uint64_t *capability_bounding_set_drop = data;
char *w;
const char *word, *state;
size_t l;
char *state;
bool invert = false;
uint64_t sum = 0;
@ -1016,12 +1013,12 @@ int config_parse_bounding_set(const char *unit,
* non-inverted everywhere to have a fully normalized
* interface. */
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
_cleanup_free_ char *t = NULL;
int r;
cap_value_t cap;
t = strndup(w, l);
t = strndup(word, l);
if (!t)
return log_oom();
@ -1163,9 +1160,8 @@ int config_parse_exec_mount_flags(const char *unit,
void *userdata) {
ExecContext *c = data;
char *w;
const char *word, *state;
size_t l;
char *state;
unsigned long flags = 0;
assert(filename);
@ -1173,10 +1169,10 @@ int config_parse_exec_mount_flags(const char *unit,
assert(rvalue);
assert(data);
FOREACH_WORD_SEPARATOR(w, l, rvalue, ", ", state) {
FOREACH_WORD_SEPARATOR(word, l, rvalue, ", ", state) {
_cleanup_free_ char *t;
t = strndup(w, l);
t = strndup(word, l);
if (!t)
return log_oom();
@ -1184,7 +1180,7 @@ int config_parse_exec_mount_flags(const char *unit,
flags = MS_SHARED;
else if (streq(t, "slave"))
flags = MS_SLAVE;
else if (streq(w, "private"))
else if (streq(word, "private"))
flags = MS_PRIVATE;
else {
log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse mount flag %s, ignoring: %s", t, rvalue);
@ -1538,7 +1534,7 @@ int config_parse_service_sockets(const char *unit,
Service *s = data;
int r;
char *state, *w;
const char *word, *state;
size_t l;
assert(filename);
@ -1546,10 +1542,10 @@ int config_parse_service_sockets(const char *unit,
assert(rvalue);
assert(data);
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
_cleanup_free_ char *t = NULL, *k = NULL;
t = strndup(w, l);
t = strndup(word, l);
if (!t)
return log_oom();
@ -1780,7 +1776,8 @@ int config_parse_environ(const char *unit,
void *userdata) {
Unit *u = userdata;
char*** env = data, *w, *state;
char*** env = data;
const char *word, *state;
size_t l;
_cleanup_free_ char *k = NULL;
int r;
@ -1809,11 +1806,11 @@ int config_parse_environ(const char *unit,
if (!k)
return log_oom();
FOREACH_WORD_QUOTED(w, l, k, state) {
FOREACH_WORD_QUOTED(word, l, k, state) {
_cleanup_free_ char *n;
char **x;
n = cunescape_length(w, l);
n = cunescape_length(word, l);
if (!n)
return log_oom();
@ -2052,20 +2049,19 @@ int config_parse_unit_requires_mounts_for(
void *userdata) {
Unit *u = userdata;
char *state;
const char *word, *state;
size_t l;
char *w;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
int r;
_cleanup_free_ char *n;
n = strndup(w, l);
n = strndup(word, l);
if (!n)
return log_oom();
@ -2156,7 +2152,7 @@ int config_parse_syscall_filter(
ExecContext *c = data;
Unit *u = userdata;
bool invert = false;
char *w, *state;
const char *word, *state;
size_t l;
int r;
@ -2209,11 +2205,11 @@ int config_parse_syscall_filter(
}
}
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
_cleanup_free_ char *t = NULL;
int id;
t = strndup(w, l);
t = strndup(word, l);
if (!t)
return log_oom();
@ -2257,7 +2253,7 @@ int config_parse_syscall_archs(
void *userdata) {
Set **archs = data;
char *w, *state;
const char *word, *state;
size_t l;
int r;
@ -2271,11 +2267,11 @@ int config_parse_syscall_archs(
if (r < 0)
return log_oom();
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
_cleanup_free_ char *t = NULL;
uint32_t a;
t = strndup(w, l);
t = strndup(word, l);
if (!t)
return log_oom();
@ -2345,7 +2341,7 @@ int config_parse_address_families(
ExecContext *c = data;
Unit *u = userdata;
bool invert = false;
char *w, *state;
const char *word, *state;
size_t l;
int r;
@ -2375,11 +2371,11 @@ int config_parse_address_families(
c->address_families_whitelist = !invert;
}
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
_cleanup_free_ char *t = NULL;
int af;
t = strndup(w, l);
t = strndup(word, l);
if (!t)
return log_oom();
@ -2874,7 +2870,8 @@ int config_parse_runtime_directory(
void *data,
void *userdata) {
char***rt = data, *w, *state;
char***rt = data;
const char *word, *state;
size_t l;
int r;
@ -2890,10 +2887,10 @@ int config_parse_runtime_directory(
return 0;
}
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
_cleanup_free_ char *n;
n = strndup(w, l);
n = strndup(word, l);
if (!n)
return log_oom();
@ -2924,9 +2921,8 @@ int config_parse_set_status(
void *data,
void *userdata) {
char *w;
size_t l;
char *state;
const char *word, *state;
int r;
ExitStatusSet *status_set = data;
@ -2941,11 +2937,11 @@ int config_parse_set_status(
return 0;
}
FOREACH_WORD(w, l, rvalue, state) {
FOREACH_WORD(word, l, rvalue, state) {
_cleanup_free_ char *temp;
int val;
temp = strndup(w, l);
temp = strndup(word, l);
if (!temp)
return log_oom();
@ -2960,11 +2956,11 @@ int config_parse_set_status(
r = set_put(status_set->signal, INT_TO_PTR(val));
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, -r, "Unable to store: %s", w);
log_syntax(unit, LOG_ERR, filename, line, -r, "Unable to store: %s", word);
return r;
}
} else {
log_syntax(unit, LOG_ERR, filename, line, -val, "Failed to parse value, ignoring: %s", w);
log_syntax(unit, LOG_ERR, filename, line, -val, "Failed to parse value, ignoring: %s", word);
return 0;
}
} else {
@ -2977,7 +2973,7 @@ int config_parse_set_status(
r = set_put(status_set->status, INT_TO_PTR(val));
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, -r, "Unable to store: %s", w);
log_syntax(unit, LOG_ERR, filename, line, -r, "Unable to store: %s", word);
return r;
}
}
@ -2999,7 +2995,8 @@ int config_parse_namespace_path_strv(
void *data,
void *userdata) {
char*** sv = data, *w, *state;
char*** sv = data;
const char *word, *state;
size_t l;
int r;
@ -3015,11 +3012,11 @@ int config_parse_namespace_path_strv(
return 0;
}
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
_cleanup_free_ char *n;
int offset;
n = strndup(w, l);
n = strndup(word, l);
if (!n)
return log_oom();

View File

@ -455,9 +455,8 @@ static int config_parse_cpu_affinity2(
void *data,
void *userdata) {
char *w;
const char *word, *state;
size_t l;
char *state;
cpu_set_t *c = NULL;
unsigned ncpus = 0;
@ -465,12 +464,12 @@ static int config_parse_cpu_affinity2(
assert(lvalue);
assert(rvalue);
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
char *t;
int r;
unsigned cpu;
if (!(t = strndup(w, l)))
if (!(t = strndup(word, l)))
return log_oom();
r = safe_atou(t, &cpu);
@ -559,7 +558,7 @@ static int config_parse_join_controllers(const char *unit,
void *userdata) {
unsigned n = 0;
char *state, *w;
const char *word, *state;
size_t length;
assert(filename);
@ -568,10 +567,10 @@ static int config_parse_join_controllers(const char *unit,
free_join_controllers();
FOREACH_WORD_QUOTED(w, length, rvalue, state) {
FOREACH_WORD_QUOTED(word, length, rvalue, state) {
char *s, **l;
s = strndup(w, length);
s = strndup(word, length);
if (!s)
return log_oom();

View File

@ -175,16 +175,16 @@ static int parse_one_option(const char *option) {
}
static int parse_options(const char *options) {
char *state, *w;
const char *word, *state;
size_t l;
int r;
assert(options);
FOREACH_WORD_SEPARATOR(w, l, options, ",", state) {
FOREACH_WORD_SEPARATOR(word, l, options, ",", state) {
_cleanup_free_ char *o;
o = strndup(w, l);
o = strndup(word, l);
if (!o)
return -ENOMEM;
r = parse_one_option(o);

View File

@ -488,23 +488,23 @@ static int help(void) {
}
static int parse_flags(const char *flag_str, int flags) {
char *w, *state;
const char *word, *state;
size_t l;
FOREACH_WORD(w, l, flag_str, state) {
if (strneq("masked", w, l))
FOREACH_WORD(word, l, flag_str, state) {
if (strneq("masked", word, l))
flags |= SHOW_MASKED;
else if (strneq ("equivalent", w, l))
else if (strneq ("equivalent", word, l))
flags |= SHOW_EQUIVALENT;
else if (strneq("redirected", w, l))
else if (strneq("redirected", word, l))
flags |= SHOW_REDIRECTED;
else if (strneq("overridden", w, l))
else if (strneq("overridden", word, l))
flags |= SHOW_OVERRIDDEN;
else if (strneq("unchanged", w, l))
else if (strneq("unchanged", word, l))
flags |= SHOW_UNCHANGED;
else if (strneq("extended", w, l))
else if (strneq("extended", word, l))
flags |= SHOW_EXTENDED;
else if (strneq("default", w, l))
else if (strneq("default", word, l))
flags |= SHOW_DEFAULTS;
else
return -EINVAL;

View File

@ -154,14 +154,14 @@ int main(int argc, char *argv[]) {
r = getenv_for_pid(1, "container_ttys", &container_ttys);
if (r > 0) {
char *w, *state;
const char *word, *state;
size_t l;
FOREACH_WORD(w, l, container_ttys, state) {
FOREACH_WORD(word, l, container_ttys, state) {
const char *t;
char tty[l + 1];
memcpy(tty, w, l);
memcpy(tty, word, l);
tty[l] = 0;
/* First strip off /dev/ if it is specified */
@ -184,15 +184,15 @@ int main(int argc, char *argv[]) {
}
if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
char *w, *state;
const char *word, *state;
size_t l;
/* Automatically add in a serial getty on all active
* kernel consoles */
FOREACH_WORD(w, l, active, state) {
FOREACH_WORD(word, l, active, state) {
_cleanup_free_ char *tty = NULL;
tty = strndup(w, l);
tty = strndup(word, l);
if (!tty) {
log_oom();
return EXIT_FAILURE;

View File

@ -1344,7 +1344,7 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_GNUTLS_LOG: {
#ifdef HAVE_GNUTLS
char *word, *state;
const char *word, *state;
size_t size;
FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {

View File

@ -1282,7 +1282,7 @@ static int setup_signals(Server *s) {
static int server_parse_proc_cmdline(Server *s) {
_cleanup_free_ char *line = NULL;
char *w, *state;
const char *w, *state;
size_t l;
int r;

View File

@ -997,7 +997,7 @@ _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) {
}
_public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
char *w, *state;
const char *word, *state;
size_t l;
unsigned long long seqnum, monotonic, realtime, xor_hash;
bool
@ -1013,18 +1013,18 @@ _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
assert_return(!journal_pid_changed(j), -ECHILD);
assert_return(!isempty(cursor), -EINVAL);
FOREACH_WORD_SEPARATOR(w, l, cursor, ";", state) {
FOREACH_WORD_SEPARATOR(word, l, cursor, ";", state) {
char *item;
int k = 0;
if (l < 2 || w[1] != '=')
if (l < 2 || word[1] != '=')
return -EINVAL;
item = strndup(w, l);
item = strndup(word, l);
if (!item)
return -ENOMEM;
switch (w[0]) {
switch (word[0]) {
case 's':
seqnum_id_set = true;
@ -1103,7 +1103,7 @@ _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
_public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
int r;
char *w, *state;
const char *word, *state;
size_t l;
Object *o;
@ -1118,20 +1118,20 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
if (r < 0)
return r;
FOREACH_WORD_SEPARATOR(w, l, cursor, ";", state) {
FOREACH_WORD_SEPARATOR(word, l, cursor, ";", state) {
_cleanup_free_ char *item = NULL;
sd_id128_t id;
unsigned long long ll;
int k = 0;
if (l < 2 || w[1] != '=')
if (l < 2 || word[1] != '=')
return -EINVAL;
item = strndup(w, l);
item = strndup(word, l);
if (!item)
return -ENOMEM;
switch (w[0]) {
switch (word[0]) {
case 's':
k = sd_id128_from_string(item+2, &id);

View File

@ -354,7 +354,7 @@ void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
int deserialize_in_addrs(struct in_addr **ret, const char *string) {
_cleanup_free_ struct in_addr *addresses = NULL;
int size = 0;
char *word, *state;
const char *word, *state;
size_t len;
assert(ret);
@ -391,7 +391,7 @@ int deserialize_in_addrs(struct in_addr **ret, const char *string) {
int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
_cleanup_free_ struct in6_addr *addresses = NULL;
int size = 0;
char *word, *state;
const char *word, *state;
size_t len;
assert(ret);
@ -446,7 +446,7 @@ void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *route
int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
_cleanup_free_ struct sd_dhcp_route *routes = NULL;
size_t size = 0, allocated = 0;
char *word, *state;
const char *word, *state;
size_t len;
assert(ret);

View File

@ -226,11 +226,10 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) {
}
_public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
char *w, *state;
_cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
size_t l;
int r;
const char *variable;
const char *word, *variable, *state;
assert_return(seat, -EINVAL);
@ -251,8 +250,8 @@ _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat)
if (asprintf(&t, UID_FMT, uid) < 0)
return -ENOMEM;
FOREACH_WORD(w, l, s, state) {
if (strneq(t, w, l))
FOREACH_WORD(word, l, s, state) {
if (strneq(t, word, l))
return 1;
}
@ -587,10 +586,10 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui
}
if (uids && t) {
char *w, *state;
const char *word, *state;
size_t l;
FOREACH_WORD(w, l, t, state)
FOREACH_WORD(word, l, t, state)
n++;
if (n > 0) {
@ -600,10 +599,10 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui
if (!b)
return -ENOMEM;
FOREACH_WORD(w, l, t, state) {
FOREACH_WORD(word, l, t, state) {
_cleanup_free_ char *k = NULL;
k = strndup(w, l);
k = strndup(word, l);
if (!k)
return -ENOMEM;
@ -789,9 +788,8 @@ _public_ int sd_machine_get_class(const char *machine, char **class) {
_public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
_cleanup_free_ char *netif = NULL;
size_t l, allocated = 0, nr = 0;
char *w, *state;
int *ni = NULL;
const char *p;
const char *p, *word, *state;
int r;
assert_return(machine_name_is_valid(machine), -EINVAL);
@ -806,11 +804,11 @@ _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
return 0;
}
FOREACH_WORD(w, l, netif, state) {
FOREACH_WORD(word, l, netif, state) {
char buf[l+1];
int ifi;
*(char*) (mempcpy(buf, w, l)) = 0;
*(char*) (mempcpy(buf, word, l)) = 0;
if (safe_atoi(buf, &ifi) < 0)
continue;

View File

@ -439,23 +439,23 @@ const char *inhibit_what_to_string(InhibitWhat w) {
InhibitWhat inhibit_what_from_string(const char *s) {
InhibitWhat what = 0;
char *w, *state;
const char *word, *state;
size_t l;
FOREACH_WORD_SEPARATOR(w, l, s, ":", state) {
if (l == 8 && strneq(w, "shutdown", l))
FOREACH_WORD_SEPARATOR(word, l, s, ":", state) {
if (l == 8 && strneq(word, "shutdown", l))
what |= INHIBIT_SHUTDOWN;
else if (l == 5 && strneq(w, "sleep", l))
else if (l == 5 && strneq(word, "sleep", l))
what |= INHIBIT_SLEEP;
else if (l == 4 && strneq(w, "idle", l))
else if (l == 4 && strneq(word, "idle", l))
what |= INHIBIT_IDLE;
else if (l == 16 && strneq(w, "handle-power-key", l))
else if (l == 16 && strneq(word, "handle-power-key", l))
what |= INHIBIT_HANDLE_POWER_KEY;
else if (l == 18 && strneq(w, "handle-suspend-key", l))
else if (l == 18 && strneq(word, "handle-suspend-key", l))
what |= INHIBIT_HANDLE_SUSPEND_KEY;
else if (l == 20 && strneq(w, "handle-hibernate-key", l))
else if (l == 20 && strneq(word, "handle-hibernate-key", l))
what |= INHIBIT_HANDLE_HIBERNATE_KEY;
else if (l == 17 && strneq(w, "handle-lid-switch", l))
else if (l == 17 && strneq(word, "handle-lid-switch", l))
what |= INHIBIT_HANDLE_LID_SWITCH;
else
return _INHIBIT_WHAT_INVALID;

View File

@ -291,14 +291,14 @@ int machine_load(Machine *m) {
if (netif) {
size_t l, allocated = 0, nr = 0;
char *w, *state;
const char *word, *state;
int *ni = NULL;
FOREACH_WORD(w, l, netif, state) {
FOREACH_WORD(word, l, netif, state) {
char buf[l+1];
int ifi;
*(char*) (mempcpy(buf, w, l)) = 0;
*(char*) (mempcpy(buf, word, l)) = 0;
if (safe_atoi(buf, &ifi) < 0)
continue;

View File

@ -395,7 +395,7 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_CAPABILITY:
case ARG_DROP_CAPABILITY: {
char *state, *word;
const char *state, *word;
size_t length;
FOREACH_WORD_SEPARATOR(word, length, optarg, ",", state) {
@ -2602,7 +2602,8 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
}
static int change_uid_gid(char **_home) {
char line[LINE_MAX], *w, *x, *state, *u, *g, *h;
char line[LINE_MAX], *x, *u, *g, *h;
const char *word, *state;
_cleanup_free_ uid_t *uids = NULL;
_cleanup_free_ char *home = NULL;
_cleanup_fclose_ FILE *f = NULL;
@ -2752,10 +2753,10 @@ static int change_uid_gid(char **_home) {
x += strcspn(x, WHITESPACE);
x += strspn(x, WHITESPACE);
FOREACH_WORD(w, l, x, state) {
FOREACH_WORD(word, l, x, state) {
char c[l+1];
memcpy(c, w, l);
memcpy(c, word, l);
c[l] = 0;
if (!GREEDY_REALLOC(uids, sz, n_uids+1))

View File

@ -304,7 +304,7 @@ static int manager_network_monitor_listen(Manager *m) {
}
static int parse_dns_server_string(Manager *m, const char *string) {
char *word, *state;
const char *word, *state;
size_t length;
int r;

View File

@ -753,9 +753,9 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
cs = strlen(controller);
FOREACH_LINE(line, f, return -errno) {
char *l, *p, *w, *e;
char *l, *p, *e;
size_t k;
char *state;
const char *word, *state;
bool found = false;
truncate_nl(line);
@ -771,16 +771,16 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
*e = 0;
FOREACH_WORD_SEPARATOR(w, k, l, ",", state) {
FOREACH_WORD_SEPARATOR(word, k, l, ",", state) {
if (k == cs && memcmp(w, controller, cs) == 0) {
if (k == cs && memcmp(word, controller, cs) == 0) {
found = true;
break;
}
if (k == 5 + cs &&
memcmp(w, "name=", 5) == 0 &&
memcmp(w+5, controller, cs) == 0) {
memcmp(word, "name=", 5) == 0 &&
memcmp(word+5, controller, cs) == 0) {
found = true;
break;
}

View File

@ -74,7 +74,8 @@ void condition_free_list(Condition *first) {
}
bool condition_test_kernel_command_line(Condition *c) {
char *line, *w, *state, *word = NULL;
char *line, *word = NULL;
const char *w, *state;
bool equal;
int r;
size_t l, pl;

View File

@ -675,7 +675,8 @@ int config_parse_strv(const char *unit,
void *data,
void *userdata) {
char *** sv = data, *w, *state;
char ***sv = data;
const char *word, *state;
size_t l;
int r;
@ -700,10 +701,10 @@ int config_parse_strv(const char *unit,
return 0;
}
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
char *n;
n = strndup(w, l);
n = strndup(word, l);
if (!n)
return log_oom();

View File

@ -170,7 +170,7 @@ int log_syntax_internal(const char *unit, int level,
void *userdata) { \
\
type **enums = data, *xs, x, *ys; \
char *w, *state; \
const char *word, *state; \
size_t l, i = 0; \
\
assert(filename); \
@ -181,10 +181,10 @@ int log_syntax_internal(const char *unit, int level,
xs = new0(type, 1); \
*xs = invalid; \
\
FOREACH_WORD(w, l, rvalue, state) { \
FOREACH_WORD(word, l, rvalue, state) { \
_cleanup_free_ char *en = NULL; \
\
en = strndup(w, l); \
en = strndup(word, l); \
if (!en) \
return -ENOMEM; \
\

View File

@ -946,20 +946,19 @@ static int config_parse_also(
void *data,
void *userdata) {
char *w;
size_t l;
char *state;
const char *word, *state;
InstallContext *c = data;
assert(filename);
assert(lvalue);
assert(rvalue);
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
_cleanup_free_ char *n;
int r;
n = strndup(w, l);
n = strndup(word, l);
if (!n)
return -ENOMEM;

View File

@ -871,11 +871,11 @@ void log_parse_environment(void) {
if (r < 0)
log_warning("Failed to read /proc/cmdline. Ignoring: %s", strerror(-r));
else if (r > 0) {
char *w, *state;
const char *word, *state;
size_t l;
FOREACH_WORD_QUOTED(w, l, line, state) {
if (l == 5 && startswith(w, "debug")) {
FOREACH_WORD_QUOTED(word, l, line, state) {
if (l == 5 && startswith(word, "debug")) {
log_set_max_level(LOG_DEBUG);
break;
}

View File

@ -574,7 +574,7 @@ int find_binary(const char *name, char **filename) {
return 0;
} else {
const char *path;
char *state, *w;
const char *word, *state;
size_t l;
/**
@ -585,10 +585,10 @@ int find_binary(const char *name, char **filename) {
if (!path)
path = DEFAULT_PATH;
FOREACH_WORD_SEPARATOR(w, l, path, ":", state) {
FOREACH_WORD_SEPARATOR(word, l, path, ":", state) {
_cleanup_free_ char *p = NULL;
if (asprintf(&p, "%.*s/%s", (int) l, w, name) < 0)
if (asprintf(&p, "%.*s/%s", (int) l, word, name) < 0)
return -ENOMEM;
if (access(p, X_OK) < 0)

View File

@ -98,7 +98,7 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states) {
}
int can_sleep_state(char **types) {
char *w, *state, **type;
char **type;
int r;
_cleanup_free_ char *p = NULL;
@ -114,11 +114,12 @@ int can_sleep_state(char **types) {
return false;
STRV_FOREACH(type, types) {
const char *word, *state;
size_t l, k;
k = strlen(*type);
FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state)
if (l == k && memcmp(w, *type, l) == 0)
FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state)
if (l == k && memcmp(word, *type, l) == 0)
return true;
}
@ -126,7 +127,7 @@ int can_sleep_state(char **types) {
}
int can_sleep_disk(char **types) {
char *w, *state, **type;
char **type;
int r;
_cleanup_free_ char *p = NULL;
@ -142,14 +143,18 @@ int can_sleep_disk(char **types) {
return false;
STRV_FOREACH(type, types) {
const char *word, *state;
size_t l, k;
k = strlen(*type);
FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) {
if (l == k && memcmp(w, *type, l) == 0)
FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state) {
if (l == k && memcmp(word, *type, l) == 0)
return true;
if (l == k + 2 && w[0] == '[' && memcmp(w + 1, *type, l - 2) == 0 && w[l-1] == ']')
if (l == k + 2 &&
word[0] == '[' &&
memcmp(word + 1, *type, l - 2) == 0 &&
word[l-1] == ']')
return true;
}
}

View File

@ -201,8 +201,7 @@ int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
}
char **strv_split(const char *s, const char *separator) {
char *state;
char *w;
const char *word, *state;
size_t l;
unsigned n, i;
char **r;
@ -210,7 +209,7 @@ char **strv_split(const char *s, const char *separator) {
assert(s);
n = 0;
FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
n++;
r = new(char*, n+1);
@ -218,8 +217,8 @@ char **strv_split(const char *s, const char *separator) {
return NULL;
i = 0;
FOREACH_WORD_SEPARATOR(w, l, s, separator, state) {
r[i] = strndup(w, l);
FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
r[i] = strndup(word, l);
if (!r[i]) {
strv_free(r);
return NULL;
@ -233,8 +232,7 @@ char **strv_split(const char *s, const char *separator) {
}
char **strv_split_quoted(const char *s) {
char *state;
char *w;
const char *word, *state;
size_t l;
unsigned n, i;
char **r;
@ -242,16 +240,19 @@ char **strv_split_quoted(const char *s) {
assert(s);
n = 0;
FOREACH_WORD_QUOTED(w, l, s, state)
FOREACH_WORD_QUOTED(word, l, s, state)
n++;
if (*state)
/* bad syntax */
return NULL;
r = new(char*, n+1);
if (!r)
return NULL;
i = 0;
FOREACH_WORD_QUOTED(w, l, s, state) {
r[i] = cunescape_length(w, l);
FOREACH_WORD_QUOTED(word, l, s, state) {
r[i] = cunescape_length(word, l);
if (!r[i]) {
strv_free(r);
return NULL;

View File

@ -415,37 +415,50 @@ static size_t strcspn_escaped(const char *s, const char *reject) {
else if (s[n] == '\\')
escaped = true;
else if (strchr(reject, s[n]))
return n;
break;
}
return n;
/* if s ends in \, return index of previous char */
return n - escaped;
}
/* Split a string into words. */
char *split(const char *c, size_t *l, const char *separator, bool quoted, char **state) {
char *current;
const char* split(const char **state, size_t *l, const char *separator, bool quoted) {
const char *current;
current = *state ? *state : (char*) c;
current = *state;
if (!*current || *c == 0)
if (!*current) {
assert(**state == '\0');
return NULL;
current += strspn(current, separator);
if (!*current)
return NULL;
if (quoted && strchr("\'\"", *current)) {
char quotechar = *(current++);
*l = strcspn_escaped(current, (char[]){quotechar, '\0'});
*state = current+*l+1;
} else if (quoted) {
*l = strcspn_escaped(current, separator);
*state = current+*l;
} else {
*l = strcspn(current, separator);
*state = current+*l;
}
return (char*) current;
current += strspn(current, separator);
if (!*current) {
*state = current;
return NULL;
}
if (quoted && strchr("\'\"", *current)) {
char quotechars[2] = {*current, '\0'};
*l = strcspn_escaped(current + 1, quotechars);
if (current[*l + 1] == '\0' ||
(current[*l + 2] && !strchr(separator, current[*l + 2]))) {
/* right quote missing or garbage at the end*/
*state = current;
return NULL;
}
assert(current[*l + 1] == quotechars[0]);
*state = current++ + *l + 2;
} else if (quoted) {
*l = strcspn_escaped(current, separator);
*state = current + *l;
} else {
*l = strcspn(current, separator);
*state = current + *l;
}
return current;
}
int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
@ -6059,7 +6072,7 @@ int split_pair(const char *s, const char *sep, char **l, char **r) {
int shall_restore_state(void) {
_cleanup_free_ char *line = NULL;
char *w, *state;
const char *word, *state;
size_t l;
int r;
@ -6071,12 +6084,12 @@ int shall_restore_state(void) {
r = 1;
FOREACH_WORD_QUOTED(w, l, line, state) {
FOREACH_WORD_QUOTED(word, l, line, state) {
const char *e;
char n[l+1];
int k;
memcpy(n, w, l);
memcpy(n, word, l);
n[l] = 0;
e = startswith(n, "systemd.restore_state=");
@ -6120,7 +6133,7 @@ int proc_cmdline(char **ret) {
int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
_cleanup_free_ char *line = NULL;
char *w, *state;
const char *w, *state;
size_t l;
int r;

View File

@ -234,7 +234,7 @@ static inline int safe_atoi64(const char *s, int64_t *ret_i) {
return safe_atolli(s, (long long int*) ret_i);
}
char *split(const char *c, size_t *l, const char *separator, bool quoted, char **state);
const char* split(const char **state, size_t *l, const char *separator, bool quoted);
#define FOREACH_WORD(word, length, s, state) \
_FOREACH_WORD(word, length, s, WHITESPACE, false, state)
@ -249,7 +249,7 @@ char *split(const char *c, size_t *l, const char *separator, bool quoted, char *
_FOREACH_WORD(word, length, s, separator, true, state)
#define _FOREACH_WORD(word, length, s, separator, quoted, state) \
for ((state) = NULL, (word) = split((s), &(length), (separator), (quoted), &(state)); (word); (word) = split((s), &(length), (separator), (quoted), &(state)))
for ((state) = (s), (word) = split(&(state), &(length), (separator), (quoted)); (word); (word) = split(&(state), &(length), (separator), (quoted)))
pid_t get_parent_of_pid(pid_t pid, pid_t *ppid);
int get_starttime_of_pid(pid_t pid, unsigned long long *st);

View File

@ -5733,7 +5733,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
return 0;
case 't': {
char *word, *state;
const char *word, *state;
size_t size;
FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
@ -5782,7 +5782,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
if (!arg_properties)
return log_oom();
} else {
char *word, *state;
const char *word, *state;
size_t size;
FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
@ -5952,7 +5952,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
break;
case ARG_STATE: {
char *word, *state;
const char *word, *state;
size_t size;
FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {

View File

@ -442,15 +442,15 @@ static int load_sysv(SysvStub *s) {
} else if (state == LSB || state == LSB_DESCRIPTION) {
if (startswith_no_case(t, "Provides:")) {
char *i, *w;
const char *word, *state_;
size_t z;
state = LSB;
FOREACH_WORD_QUOTED(w, z, t+9, i) {
FOREACH_WORD_QUOTED(word, z, t+9, state_) {
_cleanup_free_ char *n = NULL, *m = NULL;
n = strndup(w, z);
n = strndup(word, z);
if (!n)
return -ENOMEM;
@ -499,16 +499,16 @@ static int load_sysv(SysvStub *s) {
startswith_no_case(t, "Should-Start:") ||
startswith_no_case(t, "X-Start-Before:") ||
startswith_no_case(t, "X-Start-After:")) {
char *i, *w;
const char *word, *state_;
size_t z;
state = LSB;
FOREACH_WORD_QUOTED(w, z, strchr(t, ':')+1, i) {
FOREACH_WORD_QUOTED(word, z, strchr(t, ':')+1, state_) {
_cleanup_free_ char *n = NULL, *m = NULL;
bool is_before;
n = strndup(w, z);
n = strndup(word, z);
if (!n)
return -ENOMEM;

View File

@ -159,12 +159,15 @@ static void test_strv_quote_unquote(const char* const *split, const char *quoted
static void test_strv_unquote(const char *quoted, const char **list) {
_cleanup_strv_free_ char **s;
_cleanup_free_ char *j;
unsigned i = 0;
char **t;
s = strv_split_quoted(quoted);
assert_se(s);
strv_print(s);
j = strv_join(s, " | ");
assert(j);
puts(j);
STRV_FOREACH(t, s)
assert_se(streq(list[i++], *t));
@ -172,6 +175,13 @@ static void test_strv_unquote(const char *quoted, const char **list) {
assert_se(list[i] == NULL);
}
static void test_invalid_unquote(const char *quoted) {
char **s;
s = strv_split_quoted(quoted);
assert(s == NULL);
}
static void test_strv_split(void) {
char **s;
unsigned i = 0;
@ -428,7 +438,9 @@ 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_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\"garbage");
test_strv_split();
test_strv_split_newlines();

View File

@ -311,7 +311,7 @@ static void test_cunescape(void) {
}
static void test_foreach_word(void) {
char *w, *state;
const char *word, *state;
size_t l;
int i = 0;
const char test[] = "test abc d\te f ";
@ -325,13 +325,12 @@ static void test_foreach_word(void) {
NULL
};
FOREACH_WORD(w, l, test, state) {
assert_se(strneq(expected[i++], w, l));
}
FOREACH_WORD(word, l, test, state)
assert_se(strneq(expected[i++], word, l));
}
static void test_foreach_word_quoted(void) {
char *w, *state;
const char *word, *state;
size_t l;
int i = 0;
const char test[] = "test a b c 'd' e '' '' hhh '' '' \"a b c\"";
@ -352,11 +351,11 @@ static void test_foreach_word_quoted(void) {
};
printf("<%s>\n", test);
FOREACH_WORD_QUOTED(w, l, test, state) {
FOREACH_WORD_QUOTED(word, l, test, state) {
_cleanup_free_ char *t = NULL;
assert_se(t = strndup(w, l));
assert_se(strneq(expected[i++], w, l));
assert_se(t = strndup(word, l));
assert_se(strneq(expected[i++], word, l));
printf("<%s>\n", t);
}
}

View File

@ -984,17 +984,17 @@ static int manager_add_server(Manager *m, const char *server) {
}
static int manager_add_server_string(Manager *m, const char *string) {
char *w, *state;
const char *word, *state;
size_t l;
int r;
assert(m);
assert(string);
FOREACH_WORD_QUOTED(w, l, string, state) {
FOREACH_WORD_QUOTED(word, l, string, state) {
char t[l+1];
memcpy(t, w, l);
memcpy(t, word, l);
t[l] = 0;
r = manager_add_server(m, t);

View File

@ -193,7 +193,7 @@ static int load_link(link_config_ctx *ctx, const char *filename) {
static bool enable_name_policy(void) {
_cleanup_free_ char *line = NULL;
char *w, *state;
const char *word, *state;
int r;
size_t l;
@ -203,8 +203,8 @@ static bool enable_name_policy(void) {
if (r <= 0)
return true;
FOREACH_WORD_QUOTED(w, l, line, state)
if (strneq(w, "net.ifnames=0", l))
FOREACH_WORD_QUOTED(word, l, line, state)
if (strneq(word, "net.ifnames=0", l))
return false;
return true;

View File

@ -956,7 +956,7 @@ static int systemd_fds(struct udev *udev, int *rctrl, int *rnetlink) {
*/
static void kernel_cmdline_options(struct udev *udev) {
_cleanup_free_ char *line = NULL;
char *w, *state;
const char *word, *state;
size_t l;
int r;
@ -966,10 +966,10 @@ static void kernel_cmdline_options(struct udev *udev) {
if (r <= 0)
return;
FOREACH_WORD_QUOTED(w, l, line, state) {
FOREACH_WORD_QUOTED(word, l, line, state) {
char *s, *opt;
s = strndup(w, l);
s = strndup(word, l);
if (!s)
break;