mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
udev-rules: fix matching of token types that support alternative patterns
For those token types that support matching of alternative patterns,
their token values are interpreted as nulstr, so make sure the parser
does the right thing and makes these token values terminated by two
subsequent NULs so they could be safely interpreted as nulstr.
Before this fix, the following rules would result to "echo foo" invocation:
ENV{foo}=", RUN"
ENV{foo}=="bar", RUN+="echo foo"
because the value of `ENV{foo}` is treated as nulstr, and it used to match
against alternative patterns, in this case `bar`, `, RUN`, and `="echo foo`.
Fixes: 25de7aa7b9
("udev: modernize udev-rules.c")
This commit is contained in:
parent
432f1fa8c7
commit
c43ff248f9
@ -347,11 +347,10 @@ int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos) {
|
|||||||
str += is_escaped;
|
str += is_escaped;
|
||||||
if (str[0] != '"')
|
if (str[0] != '"')
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
str++;
|
|
||||||
|
|
||||||
if (!is_escaped) {
|
if (!is_escaped) {
|
||||||
/* unescape double quotation '\"'->'"' */
|
/* unescape double quotation '\"'->'"' */
|
||||||
for (i = j = str; *i != '"'; i++, j++) {
|
for (j = str, i = str + 1; *i != '"'; i++, j++) {
|
||||||
if (*i == '\0')
|
if (*i == '\0')
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (i[0] == '\\' && i[1] == '"')
|
if (i[0] == '\\' && i[1] == '"')
|
||||||
@ -359,12 +358,17 @@ int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos) {
|
|||||||
*j = *i;
|
*j = *i;
|
||||||
}
|
}
|
||||||
j[0] = '\0';
|
j[0] = '\0';
|
||||||
|
/*
|
||||||
|
* The return value must be terminated by two subsequent NULs
|
||||||
|
* so it could be safely interpreted as nulstr.
|
||||||
|
*/
|
||||||
|
j[1] = '\0';
|
||||||
} else {
|
} else {
|
||||||
_cleanup_free_ char *unescaped = NULL;
|
_cleanup_free_ char *unescaped = NULL;
|
||||||
ssize_t l;
|
ssize_t l;
|
||||||
|
|
||||||
/* find the end position of value */
|
/* find the end position of value */
|
||||||
for (i = str; *i != '"'; i++) {
|
for (i = str + 1; *i != '"'; i++) {
|
||||||
if (i[0] == '\\')
|
if (i[0] == '\\')
|
||||||
i++;
|
i++;
|
||||||
if (*i == '\0')
|
if (*i == '\0')
|
||||||
@ -372,12 +376,17 @@ int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos) {
|
|||||||
}
|
}
|
||||||
i[0] = '\0';
|
i[0] = '\0';
|
||||||
|
|
||||||
l = cunescape_length(str, i - str, 0, &unescaped);
|
l = cunescape_length(str + 1, i - (str + 1), 0, &unescaped);
|
||||||
if (l < 0)
|
if (l < 0)
|
||||||
return l;
|
return l;
|
||||||
|
|
||||||
assert(l <= i - str);
|
assert(l <= i - (str + 1));
|
||||||
memcpy(str, unescaped, l + 1);
|
memcpy(str, unescaped, l + 1);
|
||||||
|
/*
|
||||||
|
* The return value must be terminated by two subsequent NULs
|
||||||
|
* so it could be safely interpreted as nulstr.
|
||||||
|
*/
|
||||||
|
str[l + 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
*ret_value = str;
|
*ret_value = str;
|
||||||
|
@ -24,6 +24,11 @@ static void test_udev_rule_parse_value_one(const char *in, const char *expected_
|
|||||||
} else {
|
} else {
|
||||||
assert_se(streq_ptr(value, expected_value));
|
assert_se(streq_ptr(value, expected_value));
|
||||||
assert_se(endpos == str + strlen(in));
|
assert_se(endpos == str + strlen(in));
|
||||||
|
/*
|
||||||
|
* The return value must be terminated by two subsequent NULs
|
||||||
|
* so it could be safely interpreted as nulstr.
|
||||||
|
*/
|
||||||
|
assert_se(value[strlen(value) + 1] == '\0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user