mirror of
https://github.com/systemd/systemd.git
synced 2024-11-05 23:51:28 +03:00
bus: fix pattern matching
DBus-spec defines two different pattern matchings: 1) Path and namespace prefix matching. In this case, A matches B either if both are equal, or if B is fully included in the namespace of A. In other words, A has to be a prefix of B, but end with a separator character (or the following character in B must be one). This is used for path_namespace= and arg0namespace= 2) The other pattern matching is used for arg0path= which does a two-way matching. That is, A must be a prefix of B, or B a prefix of A. Furthermore, the prefix must end with a separator. Fix the sd-bus helpers to reflect that. The 'simple_' and 'complex_' prefixes don't make any sense now, but.. eh..
This commit is contained in:
parent
2e90f867f9
commit
744dccdd36
@ -211,6 +211,17 @@ bool member_name_is_valid(const char *p) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Complex pattern match
|
||||
* This checks whether @a is a 'complex-prefix' of @b, or @b is a
|
||||
* 'complex-prefix' of @a, based on strings that consist of labels with @c as
|
||||
* spearator. This function returns true if:
|
||||
* - both strings are equal
|
||||
* - either is a prefix of the other and ends with @c
|
||||
* The second rule makes sure that either string needs to be fully included in
|
||||
* the other, and the string which is considered the prefix needs to end with a
|
||||
* separator.
|
||||
*/
|
||||
static bool complex_pattern_check(char c, const char *a, const char *b) {
|
||||
bool separator = false;
|
||||
|
||||
@ -222,9 +233,7 @@ static bool complex_pattern_check(char c, const char *a, const char *b) {
|
||||
|
||||
for (;;) {
|
||||
if (*a != *b)
|
||||
return (separator && (*a == 0 || *b == 0)) ||
|
||||
(*a == 0 && *b == c && b[1] == 0) ||
|
||||
(*b == 0 && *a == c && a[1] == 0);
|
||||
return (separator && (*a == 0 || *b == 0));
|
||||
|
||||
if (*a == 0)
|
||||
return true;
|
||||
@ -243,7 +252,18 @@ bool path_complex_pattern(const char *pattern, const char *value) {
|
||||
return complex_pattern_check('/', pattern, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple pattern match
|
||||
* This checks whether @a is a 'simple-prefix' of @b, based on strings that
|
||||
* consist of labels with @c as separator. This function returns true, if:
|
||||
* - if @a and @b are equal
|
||||
* - if @a is a prefix of @b, and the first following character in @b (or the
|
||||
* last character in @a) is @c
|
||||
* The second rule basically makes sure that if @a is a prefix of @b, then @b
|
||||
* must follow with a new label separated by @c. It cannot extend the label.
|
||||
*/
|
||||
static bool simple_pattern_check(char c, const char *a, const char *b) {
|
||||
bool separator = false;
|
||||
|
||||
if (!a && !b)
|
||||
return true;
|
||||
@ -253,11 +273,13 @@ static bool simple_pattern_check(char c, const char *a, const char *b) {
|
||||
|
||||
for (;;) {
|
||||
if (*a != *b)
|
||||
return *a == 0 && *b == c;
|
||||
return *a == 0 && (*b == c || separator);
|
||||
|
||||
if (*a == 0)
|
||||
return true;
|
||||
|
||||
separator = *a == c;
|
||||
|
||||
a++, b++;
|
||||
}
|
||||
}
|
||||
|
@ -124,5 +124,15 @@ int main(int argc, char *argv[]) {
|
||||
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true);
|
||||
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/quux'", false);
|
||||
|
||||
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/'", false);
|
||||
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/'", false);
|
||||
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar/waldo/'", false);
|
||||
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/'", true);
|
||||
|
||||
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/bar/waldo", "arg0path='/foo/'", true);
|
||||
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo'", true);
|
||||
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo/bar/waldo'", false);
|
||||
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/", "arg0path='/foo/bar/waldo'", true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -95,23 +95,28 @@ int main(int argc, char *argv[]) {
|
||||
assert_se(!namespace_complex_pattern("foo.", ""));
|
||||
|
||||
assert_se(path_complex_pattern("", ""));
|
||||
assert_se(path_complex_pattern("", "/"));
|
||||
assert_se(path_complex_pattern("/", ""));
|
||||
assert_se(!path_complex_pattern("", "/"));
|
||||
assert_se(!path_complex_pattern("/", ""));
|
||||
assert_se(path_complex_pattern("/", "/"));
|
||||
assert_se(path_complex_pattern("/foobar/", "/"));
|
||||
assert_se(path_complex_pattern("/foobar/", "/foobar"));
|
||||
assert_se(!path_complex_pattern("/foobar/", "/foobar"));
|
||||
assert_se(path_complex_pattern("/foobar", "/foobar"));
|
||||
assert_se(path_complex_pattern("/foobar", "/foobar/"));
|
||||
assert_se(!path_complex_pattern("/foobar", "/foobar/"));
|
||||
assert_se(!path_complex_pattern("/foobar", "/foobar/waldo"));
|
||||
assert_se(path_complex_pattern("/foobar/", "/foobar/waldo"));
|
||||
assert_se(path_complex_pattern("/foobar/waldo", "/foobar/"));
|
||||
|
||||
assert_se(path_simple_pattern("/foo/", "/foo/bar/waldo"));
|
||||
|
||||
assert_se(namespace_simple_pattern("", ""));
|
||||
assert_se(namespace_simple_pattern("", ".foobar"));
|
||||
assert_se(namespace_simple_pattern("foobar", "foobar"));
|
||||
assert_se(namespace_simple_pattern("foobar.waldo", "foobar.waldo"));
|
||||
assert_se(namespace_simple_pattern("foobar", "foobar.waldo"));
|
||||
assert_se(!namespace_simple_pattern("foobar.waldo", "foobar"));
|
||||
assert_se(!namespace_simple_pattern("", "foo"));
|
||||
assert_se(!namespace_simple_pattern("foo", ""));
|
||||
assert_se(namespace_simple_pattern("foo.", "foo.bar.waldo"));
|
||||
|
||||
assert_se(streq(object_path_startswith("/foo/bar", "/foo"), "bar"));
|
||||
assert_se(streq(object_path_startswith("/foo", "/foo"), ""));
|
||||
|
Loading…
Reference in New Issue
Block a user