diff options
author | Lennart Poettering <lennart@poettering.net> | 2013-03-22 02:19:49 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-03-22 02:19:49 +0100 |
commit | 813a4f93750be40eff13f127dfef8364642a13bc (patch) | |
tree | 2bdc37d9287e089b48646224a225d7e3421ecc87 /src | |
parent | d728d708c3ccfcb34f6d7673f7855fbf0c10aeec (diff) |
bus: properly verify recursion depth of signatures
Diffstat (limited to 'src')
-rw-r--r-- | src/libsystemd-bus/bus-signature.c | 28 | ||||
-rw-r--r-- | src/libsystemd-bus/test-bus-signature.c | 11 |
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; } |