summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-03-22 02:19:49 +0100
committerLennart Poettering <lennart@poettering.net>2013-03-22 02:19:49 +0100
commit813a4f93750be40eff13f127dfef8364642a13bc (patch)
tree2bdc37d9287e089b48646224a225d7e3421ecc87
parentd728d708c3ccfcb34f6d7673f7855fbf0c10aeec (diff)
bus: properly verify recursion depth of signatures
-rw-r--r--src/libsystemd-bus/bus-signature.c28
-rw-r--r--src/libsystemd-bus/test-bus-signature.c11
2 files changed, 31 insertions, 8 deletions
diff --git a/src/libsystemd-bus/bus-signature.c b/src/libsystemd-bus/bus-signature.c
index db95c8870d..a92b7124c3 100644
--- a/src/libsystemd-bus/bus-signature.c
+++ b/src/libsystemd-bus/bus-signature.c
@@ -27,6 +27,8 @@
static int signature_element_length_internal(
const char *s,
bool allow_dict_entry,
+ unsigned array_depth,
+ unsigned struct_depth,
size_t *l) {
int r;
@@ -41,7 +43,10 @@ static int signature_element_length_internal(
if (*s == SD_BUS_TYPE_ARRAY) {
size_t t;
- r = signature_element_length_internal(s + 1, true, &t);
+ if (array_depth >= 32)
+ return -EINVAL;
+
+ r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
if (r < 0)
return r;
@@ -52,10 +57,13 @@ static int signature_element_length_internal(
if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
const char *p = s + 1;
+ if (struct_depth >= 32)
+ return -EINVAL;
+
while (*p != SD_BUS_TYPE_STRUCT_END) {
size_t t;
- r = signature_element_length_internal(p, false, &t);
+ r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
if (r < 0)
return r;
@@ -70,13 +78,16 @@ static int signature_element_length_internal(
const char *p = s + 1;
unsigned n = 0;
+ if (struct_depth >= 32)
+ return -EINVAL;
+
while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
size_t t;
if (n == 0 && !bus_type_is_basic(*p))
return -EINVAL;
- r = signature_element_length_internal(p, false, &t);
+ r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
if (r < 0)
return r;
@@ -94,6 +105,11 @@ static int signature_element_length_internal(
return -EINVAL;
}
+
+int signature_element_length(const char *s, size_t *l) {
+ return signature_element_length_internal(s, true, 0, 0, l);
+}
+
bool signature_is_single(const char *s) {
int r;
size_t t;
@@ -126,7 +142,7 @@ bool signature_is_valid(const char *s, bool allow_dict_entry) {
while (*p) {
size_t t;
- r = signature_element_length_internal(p, allow_dict_entry, &t);
+ r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
if (r < 0)
return false;
@@ -135,7 +151,3 @@ bool signature_is_valid(const char *s, bool allow_dict_entry) {
return p - s <= 255;
}
-
-int signature_element_length(const char *s, size_t *l) {
- return signature_element_length_internal(s, true, l);
-}
diff --git a/src/libsystemd-bus/test-bus-signature.c b/src/libsystemd-bus/test-bus-signature.c
index 4310d62e0a..5bc4310e7c 100644
--- a/src/libsystemd-bus/test-bus-signature.c
+++ b/src/libsystemd-bus/test-bus-signature.c
@@ -70,5 +70,16 @@ int main(int argc, char *argv[]) {
assert_se(signature_is_valid("sssusa(uuubbba(uu)uuuu)a{u(uuuvas)}", false));
+ assert_se(!signature_is_valid("a", false));
+ assert_se(signature_is_valid("as", false));
+ assert_se(signature_is_valid("aas", false));
+ assert_se(signature_is_valid("aaas", false));
+ assert_se(signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad", false));
+ 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("((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))", false));
+
return 0;
}