1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-10-28 20:25:25 +03:00

Merge pull request #774 from dvdhrm/gvariant3

gvariant: fix encoding of unary type and root-variant (v3)
This commit is contained in:
Lennart Poettering 2015-07-29 18:20:17 +02:00
commit 2b32ffa07d
4 changed files with 62 additions and 24 deletions

View File

@ -75,14 +75,19 @@ int bus_gvariant_get_size(const char *signature) {
case SD_BUS_TYPE_STRUCT_BEGIN: case SD_BUS_TYPE_STRUCT_BEGIN:
case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
char t[n-1]; if (n == 2) {
/* unary type () has fixed size of 1 */
r = 1;
} else {
char t[n-1];
memcpy(t, p + 1, n - 2); memcpy(t, p + 1, n - 2);
t[n - 2] = 0; t[n - 2] = 0;
r = bus_gvariant_get_size(t); r = bus_gvariant_get_size(t);
if (r < 0) if (r < 0)
return r; return r;
}
sum += r; sum += r;
break; break;

View File

@ -2209,7 +2209,14 @@ static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c,
assert(!c->need_offsets || i == c->n_offsets); assert(!c->need_offsets || i == c->n_offsets);
assert(c->need_offsets || n_variable == 0); assert(c->need_offsets || n_variable == 0);
if (n_variable <= 0) { if (isempty(c->signature)) {
/* The unary type is encoded as fixed 1 byte padding */
a = message_extend_body(m, 1, 1, add_offset, false);
if (!a)
return -ENOMEM;
*a = 0;
} else if (n_variable <= 0) {
int alignment = 1; int alignment = 1;
/* Structures with fixed-size members only have to be /* Structures with fixed-size members only have to be
@ -2899,18 +2906,20 @@ static int bus_message_close_header(sd_bus_message *m) {
signature = strempty(m->root_container.signature); signature = strempty(m->root_container.signature);
l = strlen(signature); l = strlen(signature);
sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l, 1); sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
d = message_extend_body(m, 1, 1 + l + sz, false, true); d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
if (!d) if (!d)
return -ENOMEM; return -ENOMEM;
*(uint8_t*) d = 0; *(uint8_t*) d = 0;
memcpy((uint8_t*) d + 1, signature, l); *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
memcpy((uint8_t*) d + 2, signature, l);
*((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
bus_gvariant_write_word_le((uint8_t*) d + 1 + l, sz, sizeof(struct bus_header) + m->fields_size); bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
m->footer = d; m->footer = d;
m->footer_accessible = 1 + l + sz; m->footer_accessible = 1 + l + 2 + sz;
} else { } else {
m->header->dbus1.fields_size = m->fields_size; m->header->dbus1.fields_size = m->fields_size;
m->header->dbus1.body_size = m->body_size; m->header->dbus1.body_size = m->body_size;
@ -3814,6 +3823,14 @@ static int build_struct_offsets(
assert(n_offsets); assert(n_offsets);
if (isempty(signature)) { if (isempty(signature)) {
/* Unary type is encoded as *fixed* 1 byte padding */
r = message_peek_body(m, &m->rindex, 1, 1, &q);
if (r < 0)
return r;
if (*(uint8_t *) q != 0)
return -EBADMSG;
*item_size = 0; *item_size = 0;
*offsets = NULL; *offsets = NULL;
*n_offsets = 0; *n_offsets = 0;
@ -3954,12 +3971,6 @@ static int enter_struct_or_dict_entry(
if (r < 0) if (r < 0)
return r; return r;
} else if (c->item_size <= 0) {
/* gvariant empty struct */
*item_size = 0;
*offsets = NULL;
*n_offsets = 0;
} else } else
/* gvariant with contents */ /* gvariant with contents */
return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets); return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
@ -4146,7 +4157,14 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m,
w->before = before; w->before = before;
w->begin = m->rindex; w->begin = m->rindex;
w->end = m->rindex + c->item_size;
/* Unary type has fixed size of 1, but virtual size of 0 */
if (BUS_MESSAGE_IS_GVARIANT(m) &&
type == SD_BUS_TYPE_STRUCT &&
isempty(signature))
w->end = m->rindex + 0;
else
w->end = m->rindex + c->item_size;
w->array_size = array_size; w->array_size = array_size;
w->item_size = item_size; w->item_size = item_size;
@ -4756,7 +4774,6 @@ _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
r = sd_bus_message_skip(m, s); r = sd_bus_message_skip(m, s);
if (r < 0) if (r < 0)
return r; return r;
assert(r != 0);
r = sd_bus_message_exit_container(m); r = sd_bus_message_exit_container(m);
if (r < 0) if (r < 0)
@ -5164,11 +5181,21 @@ int bus_message_parse_fields(sd_bus_message *m) {
return -EBADMSG; return -EBADMSG;
if (*p == 0) { if (*p == 0) {
size_t l;
char *c; char *c;
/* We found the beginning of the signature string, yay! */ /* We found the beginning of the signature
* string, yay! We require the body to be a
* structure, so verify it and then strip the
* opening/closing brackets. */
c = strndup(p + 1, ((char*) m->footer + m->footer_accessible) - p - (1 + sz)); l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
if (l < 2 ||
p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
return -EBADMSG;
c = strndup(p + 1 + 1, l - 2);
if (!c) if (!c)
return -ENOMEM; return -ENOMEM;

View File

@ -59,7 +59,7 @@ static void test_bus_gvariant_is_fixed_size(void) {
static void test_bus_gvariant_get_size(void) { static void test_bus_gvariant_get_size(void) {
assert_se(bus_gvariant_get_size("") == 0); assert_se(bus_gvariant_get_size("") == 0);
assert_se(bus_gvariant_get_size("()") == 0); assert_se(bus_gvariant_get_size("()") == 1);
assert_se(bus_gvariant_get_size("y") == 1); assert_se(bus_gvariant_get_size("y") == 1);
assert_se(bus_gvariant_get_size("u") == 4); assert_se(bus_gvariant_get_size("u") == 4);
assert_se(bus_gvariant_get_size("b") == 1); assert_se(bus_gvariant_get_size("b") == 1);

View File

@ -134,6 +134,9 @@ int main(int argc, char *argv[]) {
r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10); r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10);
assert_se(r >= 0); assert_se(r >= 0);
r = sd_bus_message_append(m, "()");
assert_se(r >= 0);
r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3"); r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3");
assert_se(r >= 0); assert_se(r >= 0);
@ -271,6 +274,9 @@ int main(int argc, char *argv[]) {
assert_se(r > 0); assert_se(r > 0);
assert_se(v == 10); assert_se(v == 10);
r = sd_bus_message_read(m, "()");
assert_se(r > 0);
r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d); r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d);
assert_se(r > 0); assert_se(r > 0);
assert_se(boolean); assert_se(boolean);
@ -350,7 +356,7 @@ int main(int argc, char *argv[]) {
assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0); assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0);
r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y"); r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y()");
assert_se(r >= 0); assert_se(r >= 0);
assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0); assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0);