diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2018-07-09 10:52:51 +0200 |
---|---|---|
committer | Sven Eden <sven.eden@prydeworx.com> | 2018-10-29 10:18:27 +0100 |
commit | 953d34afc6caca8cdf531ba78c697b64a46f36e6 (patch) | |
tree | 45e0cd510f8d0b98c2ea33279eb11a6343d231d7 /src/libelogind/sd-bus | |
parent | 4893a7051cee17b26a458090da80c7470f9be3d6 (diff) |
bus-message: avoid an infinite loop on empty structures
The alternative would be to treat gvariant and !gvariant messages differently.
But this is a problem because we check signatures is variuos places before we
have an actual message, for example in sd_bus_add_object_vtable(). It seems
better to treat things consistent (i.e. follow the lowest common denominator)
and disallow empty structures everywhere.
(cherry picked from commit ec6bda56cbca9509b1abde1122645630caca877c)
Diffstat (limited to 'src/libelogind/sd-bus')
-rw-r--r-- | src/libelogind/sd-bus/bus-message.c | 3 | ||||
-rw-r--r-- | src/libelogind/sd-bus/bus-signature.c | 6 | ||||
-rw-r--r-- | src/libelogind/sd-bus/test-bus-signature.c | 8 |
3 files changed, 12 insertions, 5 deletions
diff --git a/src/libelogind/sd-bus/bus-message.c b/src/libelogind/sd-bus/bus-message.c index dca45e06c..aa4216628 100644 --- a/src/libelogind/sd-bus/bus-message.c +++ b/src/libelogind/sd-bus/bus-message.c @@ -4172,6 +4172,7 @@ _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char /* signature_element_length does verification internally */ + /* The array element must not be empty */ assert(l >= 1); if (free_and_strndup(&c->peeked_signature, c->signature + c->index + 1, l) < 0) @@ -4195,7 +4196,7 @@ _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char if (r < 0) return r; - assert(l >= 2); + assert(l >= 3); if (free_and_strndup(&c->peeked_signature, c->signature + c->index + 1, l - 2) < 0) return -ENOMEM; diff --git a/src/libelogind/sd-bus/bus-signature.c b/src/libelogind/sd-bus/bus-signature.c index 18c91e870..1ca37cbb5 100644 --- a/src/libelogind/sd-bus/bus-signature.c +++ b/src/libelogind/sd-bus/bus-signature.c @@ -58,6 +58,12 @@ static int signature_element_length_internal( p += t; } + if (p - s < 2) + /* D-Bus spec: Empty structures are not allowed; there + * must be at least one type code between the parentheses. + */ + return -EINVAL; + *l = p - s + 1; return 0; } diff --git a/src/libelogind/sd-bus/test-bus-signature.c b/src/libelogind/sd-bus/test-bus-signature.c index 1ba190919..a716cd1b3 100644 --- a/src/libelogind/sd-bus/test-bus-signature.c +++ b/src/libelogind/sd-bus/test-bus-signature.c @@ -16,9 +16,9 @@ int main(int argc, char *argv[]) { assert_se(signature_is_single("v", false)); assert_se(signature_is_single("as", false)); assert_se(signature_is_single("(ss)", false)); - assert_se(signature_is_single("()", false)); - assert_se(signature_is_single("(()()()()())", false)); - assert_se(signature_is_single("(((())))", false)); + assert_se(!signature_is_single("()", false)); + assert_se(!signature_is_single("(()()()()())", false)); + assert_se(!signature_is_single("(((())))", false)); assert_se(signature_is_single("((((s))))", false)); assert_se(signature_is_single("{ss}", true)); assert_se(signature_is_single("a{ss}", false)); @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) { assert_se(signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas", false)); assert_se(!signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaau", false)); - assert_se(signature_is_valid("(((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))", false)); + assert_se(signature_is_valid("((((((((((((((((((((((((((((((((s))))))))))))))))))))))))))))))))", false)); assert_se(!signature_is_valid("((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))", false)); assert_se(namespace_complex_pattern("", "")); |