diff options
-rw-r--r-- | src/libsystemd/sd-bus/bus-message.c | 17 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/test-bus-marshal.c | 21 |
2 files changed, 36 insertions, 2 deletions
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 2959303033..3d6f8c20cc 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -2179,6 +2179,7 @@ static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) } static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) { + bool fixed_size = true; size_t n_variable = 0; unsigned i = 0; const char *p; @@ -2214,6 +2215,8 @@ static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, /* We need to add an offset for each item that has a * variable size and that is not the last one in the * list */ + if (r == 0) + fixed_size = false; if (r == 0 && p[n] != 0) n_variable++; @@ -2225,7 +2228,19 @@ static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, assert(c->need_offsets || n_variable == 0); if (n_variable <= 0) { - a = message_extend_body(m, 1, 0, add_offset, false); + int alignment = 1; + + /* Structures with fixed-size members only have to be + * fixed-size themselves. But gvariant requires all fixed-size + * elements to be sized a multiple of their alignment. Hence, + * we must *always* add final padding after the last member so + * the overall size of the structure is properly aligned. */ + if (fixed_size) + alignment = bus_gvariant_get_alignment(strempty(c->signature)); + + assert(alignment > 0); + + a = message_extend_body(m, alignment, 0, add_offset, false); if (!a) return -ENOMEM; } else { diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c index d95a03c221..746df7bf5c 100644 --- a/src/libsystemd/sd-bus/test-bus-marshal.c +++ b/src/libsystemd/sd-bus/test-bus-marshal.c @@ -123,6 +123,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); @@ -244,6 +247,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); @@ -323,7 +342,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); |