summaryrefslogtreecommitdiff
path: root/src/libelogind/sd-bus
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2018-07-09 10:52:51 +0200
committerSven Eden <sven.eden@prydeworx.com>2018-10-29 10:18:27 +0100
commit953d34afc6caca8cdf531ba78c697b64a46f36e6 (patch)
tree45e0cd510f8d0b98c2ea33279eb11a6343d231d7 /src/libelogind/sd-bus
parent4893a7051cee17b26a458090da80c7470f9be3d6 (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.c3
-rw-r--r--src/libelogind/sd-bus/bus-signature.c6
-rw-r--r--src/libelogind/sd-bus/test-bus-signature.c8
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("", ""));