From 443a55981388f519fb6528a8ee042f9e69079b68 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Thu, 16 Jul 2015 11:00:55 +0200 Subject: sd-bus: fix gvariant structure encoding In gvariant, all fixed-size objects need to be sized a multiple of their alignment. If a structure has only fixed-size members, it is required to be fixed size itself. If you imagine a structure like (ty), you have an 8-byte member followed by an 1-byte member. Hence, the overall inner-size is 9. The alignment of the object is 8, though. Therefore, the specs mandates final padding after fixed-size structures, to make sure it's sized a multiple of its alignment (=> 16). On the gvariant decoder side, we already account for this in bus_gvariant_get_size(), as we apply overall padding to the size of the structure. Therefore, our decoder correctly skips such final padding when parsing fixed-size structure. On the gvariant encoder side, however, we don't account for this final padding. This patch fixes the structure and dict-entry encoders to properly place such padding at the end of non-uniform fixed-size structures. The problem can be easily seen by running: $ busctl --user monitor and $ busctl call --user org.freedesktop.systemd1 / org.foobar foobar "(ty)" 777 8 The monitor will fail to parse the message and print an error. With this patch applied, everything works fine again. This patch also adds a bunch of test-cases to force non-uniform structures with non-pre-aligned positions. Thanks to Jan Alexander Steffens for spotting this and narrowing it down to non-uniform gvariant structures. Fixes #597. --- src/libsystemd/sd-bus/test-bus-marshal.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'src/libsystemd/sd-bus/test-bus-marshal.c') diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c index a866a56179..73c6e41c85 100644 --- a/src/libsystemd/sd-bus/test-bus-marshal.c +++ b/src/libsystemd/sd-bus/test-bus-marshal.c @@ -131,6 +131,9 @@ int main(int argc, char *argv[]) { r = sd_bus_message_append(m, "a{yv}", 2, 3, "s", "foo", 5, "s", "waldo"); assert_se(r >= 0); + r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777, 7, 9, 77, 7777, 10); + assert_se(r >= 0); + r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3"); assert_se(r >= 0); @@ -252,6 +255,22 @@ int main(int argc, char *argv[]) { assert_se(v == 5); assert_se(streq(y, "waldo")); + r = sd_bus_message_read(m, "y(ty)", &v, &u64, &u); + assert_se(r > 0); + assert_se(v == 8); + assert_se(u64 == 777); + assert_se(u == 7); + + r = sd_bus_message_read(m, "y(yt)", &v, &u, &u64); + assert_se(r > 0); + assert_se(v == 9); + assert_se(u == 77); + assert_se(u64 == 7777); + + r = sd_bus_message_read(m, "y", &v); + assert_se(r > 0); + assert_se(v == 10); + r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d); assert_se(r > 0); assert_se(boolean); @@ -331,7 +350,7 @@ int main(int argc, char *argv[]) { assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0); - r = sd_bus_message_skip(m, "a{yv}"); + r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y"); assert_se(r >= 0); assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0); -- cgit v1.2.3-54-g00ecf