#include "sd-bus.h"
#include "alloc-util.h"
-#include "bus-gvariant.h"
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-signature.h"
free(c->signature);
free(c->peeked_signature);
- free(c->offsets);
/* Move to previous container, but not if we are on root container */
if (m->n_containers > 0)
assert(m);
- /* dbus1 only allows 8bit header field ids */
+ /* dbus only allows 8bit header field ids */
if (h > 0xFF)
return -EINVAL;
- /* dbus1 doesn't allow strings over 32bit, let's enforce this
- * globally, to not risk convertability */
+ /* dbus doesn't allow strings over 32bit */
l = strlen(s);
if (l > UINT32_MAX)
return -EINVAL;
/* Signature "(yv)" where the variant contains "s" */
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
-
- /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
- p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
- if (!p)
- return -ENOMEM;
-
- *((uint64_t*) p) = h;
- memcpy(p+8, s, l);
- p[8+l] = 0;
- p[8+l+1] = 0;
- p[8+l+2] = type;
-
- if (ret)
- *ret = (char*) p + 8;
-
- } else {
- /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
- p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
- if (!p)
- return -ENOMEM;
+ /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
+ p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
+ if (!p)
+ return -ENOMEM;
- p[0] = (uint8_t) h;
- p[1] = 1;
- p[2] = type;
- p[3] = 0;
+ p[0] = (uint8_t) h;
+ p[1] = 1;
+ p[2] = type;
+ p[3] = 0;
- ((uint32_t*) p)[1] = l;
- memcpy(p + 8, s, l + 1);
+ ((uint32_t*) p)[1] = l;
+ memcpy(p + 8, s, l + 1);
- if (ret)
- *ret = (char*) p + 8;
- }
+ if (ret)
+ *ret = (char*) p + 8;
return 0;
}
assert(m);
- /* dbus1 only allows 8bit header field ids */
+ /* dbus only allows 8bit header field ids */
if (h > 0xFF)
return -EINVAL;
- /* dbus1 doesn't allow signatures over 8bit, let's enforce
- * this globally, to not risk convertability */
+ /* dbus doesn't allow signatures over 8bit */
l = strlen(s);
if (l > SD_BUS_MAXIMUM_SIGNATURE_LENGTH)
return -EINVAL;
/* Signature "(yv)" where the variant contains "g" */
- if (BUS_MESSAGE_IS_GVARIANT(m))
- /* For gvariant the serialization is the same as for normal strings */
- return message_append_field_string(m, h, 'g', s, ret);
- else {
- /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
- p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
- if (!p)
- return -ENOMEM;
+ /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
+ p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
+ if (!p)
+ return -ENOMEM;
- p[0] = (uint8_t) h;
- p[1] = 1;
- p[2] = SD_BUS_TYPE_SIGNATURE;
- p[3] = 0;
- p[4] = l;
- memcpy(p + 5, s, l + 1);
+ p[0] = (uint8_t) h;
+ p[1] = 1;
+ p[2] = SD_BUS_TYPE_SIGNATURE;
+ p[3] = 0;
+ p[4] = l;
+ memcpy(p + 5, s, l + 1);
- if (ret)
- *ret = (const char*) p + 5;
- }
+ if (ret)
+ *ret = (const char*) p + 5;
return 0;
}
assert(m);
- /* dbus1 only allows 8bit header field ids */
- if (h > 0xFF)
- return -EINVAL;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- /* (field id 64bit + ((value + NUL + signature string 'u') */
-
- p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
- if (!p)
- return -ENOMEM;
-
- *((uint64_t*) p) = h;
- *((uint32_t*) (p + 8)) = x;
- p[12] = 0;
- p[13] = 'u';
- } else {
- /* (field id byte + (signature length + signature 'u' + NUL) + value) */
- p = message_extend_fields(m, 8, 4 + 4, false);
- if (!p)
- return -ENOMEM;
-
- p[0] = (uint8_t) h;
- p[1] = 1;
- p[2] = 'u';
- p[3] = 0;
-
- ((uint32_t*) p)[1] = x;
- }
-
- return 0;
-}
-
-static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
- uint8_t *p;
-
- assert(m);
-
- /* dbus1 only allows 8bit header field ids */
+ /* dbus only allows 8bit header field ids */
if (h > 0xFF)
return -EINVAL;
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- /* (field id 64bit + ((value + NUL + signature string 't') */
-
- p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
- if (!p)
- return -ENOMEM;
-
- *((uint64_t*) p) = h;
- *((uint64_t*) (p + 8)) = x;
- p[16] = 0;
- p[17] = 't';
- } else {
- /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
- p = message_extend_fields(m, 8, 4 + 4 + 8, false);
- if (!p)
- return -ENOMEM;
+ /* (field id byte + (signature length + signature 'u' + NUL) + value) */
+ p = message_extend_fields(m, 8, 4 + 4, false);
+ if (!p)
+ return -ENOMEM;
- p[0] = (uint8_t) h;
- p[1] = 1;
- p[2] = 't';
- p[3] = 0;
- p[4] = 0;
- p[5] = 0;
- p[6] = 0;
- p[7] = 0;
+ p[0] = (uint8_t) h;
+ p[1] = 1;
+ p[2] = 'u';
+ p[3] = 0;
- ((uint64_t*) p)[1] = x;
- }
+ ((uint32_t*) p)[1] = x;
return 0;
}
static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
assert(m);
- if (BUS_MESSAGE_IS_GVARIANT(m))
- return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
- else {
- /* 64bit cookies are not supported on dbus1 */
- if (cookie > UINT32_MAX)
- return -EOPNOTSUPP;
+ /* 64bit cookies are not supported */
+ if (cookie > UINT32_MAX)
+ return -EOPNOTSUPP;
- return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
- }
+ return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
}
static int message_from_header(
sd_bus *bus,
- void *header,
- size_t header_accessible,
- void *footer,
- size_t footer_accessible,
+ void *buffer,
size_t message_size,
int *fds,
size_t n_fds,
const char *label,
- size_t extra,
sd_bus_message **ret) {
_cleanup_free_ sd_bus_message *m = NULL;
size_t a, label_sz = 0; /* avoid false maybe-uninitialized warning */
assert(bus);
- assert(header || header_accessible <= 0);
- assert(footer || footer_accessible <= 0);
+ assert(buffer || message_size <= 0);
assert(fds || n_fds <= 0);
assert(ret);
- if (header_accessible < sizeof(struct bus_header))
- return -EBADMSG;
-
- if (header_accessible > message_size)
- return -EBADMSG;
- if (footer_accessible > message_size)
+ if (message_size < sizeof(struct bus_header))
return -EBADMSG;
- h = header;
+ h = buffer;
if (!IN_SET(h->version, 1, 2))
return -EBADMSG;
/* Note that we are happy with unknown flags in the flags header! */
- a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
+ a = ALIGN(sizeof(sd_bus_message));
if (label) {
label_sz = strlen(label);
return -ENOMEM;
m->sealed = true;
- m->header = header;
- m->header_accessible = header_accessible;
- m->footer = footer;
- m->footer_accessible = footer_accessible;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- size_t ws;
-
- if (h->dbus2.cookie == 0)
- return -EBADMSG;
-
- /* dbus2 derives the sizes from the message size and
- the offset table at the end, since it is formatted as
- gvariant "yyyyuta{tv}v". Since the message itself is a
- structure with precisely to variable sized entries,
- there's only one offset in the table, which marks the
- end of the fields array. */
-
- ws = bus_gvariant_determine_word_size(message_size, 0);
- if (footer_accessible < ws)
- return -EBADMSG;
+ m->header = buffer;
- m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
- if (ALIGN8(m->fields_size) > message_size - ws)
- return -EBADMSG;
- if (m->fields_size < sizeof(struct bus_header))
- return -EBADMSG;
-
- m->fields_size -= sizeof(struct bus_header);
- m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
- } else {
- if (h->dbus1.serial == 0)
- return -EBADMSG;
+ if (h->serial == 0)
+ return -EBADMSG;
- /* dbus1 has the sizes in the header */
- m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
- m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
+ m->fields_size = BUS_MESSAGE_BSWAP32(m, h->fields_size);
+ m->body_size = BUS_MESSAGE_BSWAP32(m, h->body_size);
- assert(message_size >= sizeof(struct bus_header));
- if (ALIGN8(m->fields_size) > message_size - sizeof(struct bus_header) ||
- m->body_size != message_size - sizeof(struct bus_header) - ALIGN8(m->fields_size))
- return -EBADMSG;
- }
+ assert(message_size >= sizeof(struct bus_header));
+ if (ALIGN8(m->fields_size) > message_size - sizeof(struct bus_header) ||
+ m->body_size != message_size - sizeof(struct bus_header) - ALIGN8(m->fields_size))
+ return -EBADMSG;
m->fds = fds;
m->n_fds = n_fds;
if (label) {
- m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
+ m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message));
memcpy(m->creds.label, label, label_sz + 1);
m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
r = message_from_header(
bus,
- buffer, length, /* in this case the initial bytes and the final bytes are the same */
buffer, length,
- length,
fds, n_fds,
label,
- 0, &m);
+ &m);
if (r < 0)
return r;
t->header->type = type;
t->header->version = bus->message_version;
t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING);
- t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t);
if (bus->allow_interactive_authorization)
t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
return 0;
}
-static int message_add_offset(sd_bus_message *m, size_t offset) {
- struct bus_container *c;
-
- assert(m);
- assert(BUS_MESSAGE_IS_GVARIANT(m));
-
- /* Add offset to current container, unless this is the first
- * item in it, which will have the 0 offset, which we can
- * ignore. */
- c = message_get_last_container(m);
-
- if (!c->need_offsets)
- return 0;
-
- if (!GREEDY_REALLOC(c->offsets, c->n_offsets + 1))
- return -ENOMEM;
-
- c->offsets[c->n_offsets++] = offset;
- return 0;
-}
-
static void message_extend_containers(sd_bus_message *m, size_t expand) {
assert(m);
static void *message_extend_body(
sd_bus_message *m,
size_t align,
- size_t sz,
- bool add_offset,
- bool force_inline) {
+ size_t sz) {
size_t start_body, end_body, padding, added;
void *p;
add_new_part =
m->n_body_parts <= 0 ||
m->body_end->sealed ||
- (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
- (force_inline && m->body_end->size > MEMFD_MIN_SIZE);
+ (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size);
/* If this must be an inlined extension, let's create a new part if
* the previous part is large enough to be inlined. */
m->body_size = end_body;
message_extend_containers(m, added);
- if (add_offset) {
- r = message_add_offset(m, end_body);
- if (r < 0) {
- m->poisoned = true;
- return NULL;
- }
- }
-
return p;
}
_cleanup_close_ int fd = -1;
struct bus_container *c;
ssize_t align, sz;
+ uint32_t u32;
void *a;
assert_return(m, -EINVAL);
}
}
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- uint8_t u8;
- uint32_t u32;
-
- switch (type) {
-
- case SD_BUS_TYPE_SIGNATURE:
- case SD_BUS_TYPE_STRING:
- p = strempty(p);
-
- _fallthrough_;
- case SD_BUS_TYPE_OBJECT_PATH:
- if (!p)
- return -EINVAL;
-
- align = 1;
- sz = strlen(p) + 1;
- break;
-
- case SD_BUS_TYPE_BOOLEAN:
-
- u8 = p && *(int*) p;
- p = &u8;
-
- align = sz = 1;
- break;
-
- case SD_BUS_TYPE_UNIX_FD:
-
- if (!p)
- return -EINVAL;
-
- fd = message_push_fd(m, *(int*) p);
- if (fd < 0)
- return fd;
-
- u32 = m->n_fds;
- p = &u32;
-
- align = sz = 4;
- break;
-
- default:
- align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
- sz = bus_gvariant_get_size(CHAR_TO_STR(type));
- break;
- }
-
- assert(align > 0);
- assert(sz > 0);
-
- a = message_extend_body(m, align, sz, true, false);
- if (!a)
- return -ENOMEM;
-
- memcpy(a, p, sz);
-
- if (stored)
- *stored = (const uint8_t*) a;
-
- } else {
- uint32_t u32;
-
- switch (type) {
+ switch (type) {
- case SD_BUS_TYPE_STRING:
- /* To make things easy we'll serialize a NULL string
- * into the empty string */
- p = strempty(p);
+ case SD_BUS_TYPE_STRING:
+ /* To make things easy we'll serialize a NULL string
+ * into the empty string */
+ p = strempty(p);
- _fallthrough_;
- case SD_BUS_TYPE_OBJECT_PATH:
+ _fallthrough_;
+ case SD_BUS_TYPE_OBJECT_PATH:
- if (!p)
- return -EINVAL;
+ if (!p)
+ return -EINVAL;
- align = 4;
- sz = 4 + strlen(p) + 1;
- break;
+ align = 4;
+ sz = 4 + strlen(p) + 1;
+ break;
- case SD_BUS_TYPE_SIGNATURE:
+ case SD_BUS_TYPE_SIGNATURE:
- p = strempty(p);
+ p = strempty(p);
- align = 1;
- sz = 1 + strlen(p) + 1;
- break;
+ align = 1;
+ sz = 1 + strlen(p) + 1;
+ break;
- case SD_BUS_TYPE_BOOLEAN:
+ case SD_BUS_TYPE_BOOLEAN:
- u32 = p && *(int*) p;
- p = &u32;
+ u32 = p && *(int*) p;
+ p = &u32;
- align = sz = 4;
- break;
+ align = sz = 4;
+ break;
- case SD_BUS_TYPE_UNIX_FD:
+ case SD_BUS_TYPE_UNIX_FD:
- if (!p)
- return -EINVAL;
+ if (!p)
+ return -EINVAL;
- fd = message_push_fd(m, *(int*) p);
- if (fd < 0)
- return fd;
+ fd = message_push_fd(m, *(int*) p);
+ if (fd < 0)
+ return fd;
- u32 = m->n_fds;
- p = &u32;
+ u32 = m->n_fds;
+ p = &u32;
- align = sz = 4;
- break;
+ align = sz = 4;
+ break;
- default:
- align = bus_type_get_alignment(type);
- sz = bus_type_get_size(type);
- break;
- }
+ default:
+ align = bus_type_get_alignment(type);
+ sz = bus_type_get_size(type);
+ break;
+ }
- assert(align > 0);
- assert(sz > 0);
+ assert(align > 0);
+ assert(sz > 0);
- a = message_extend_body(m, align, sz, false, false);
- if (!a)
- return -ENOMEM;
+ a = message_extend_body(m, align, sz);
+ if (!a)
+ return -ENOMEM;
- if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
- *(uint32_t*) a = sz - 5;
- memcpy((uint8_t*) a + 4, p, sz - 4);
+ if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
+ *(uint32_t*) a = sz - 5;
+ memcpy((uint8_t*) a + 4, p, sz - 4);
- if (stored)
- *stored = (const uint8_t*) a + 4;
+ if (stored)
+ *stored = (const uint8_t*) a + 4;
- } else if (type == SD_BUS_TYPE_SIGNATURE) {
- *(uint8_t*) a = sz - 2;
- memcpy((uint8_t*) a + 1, p, sz - 1);
+ } else if (type == SD_BUS_TYPE_SIGNATURE) {
+ *(uint8_t*) a = sz - 2;
+ memcpy((uint8_t*) a + 1, p, sz - 1);
- if (stored)
- *stored = (const uint8_t*) a + 1;
- } else {
- memcpy(a, p, sz);
+ if (stored)
+ *stored = (const uint8_t*) a + 1;
+ } else {
+ memcpy(a, p, sz);
- if (stored)
- *stored = a;
- }
+ if (stored)
+ *stored = a;
}
if (type == SD_BUS_TYPE_UNIX_FD)
}
}
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- a = message_extend_body(m, 1, size + 1, true, false);
- if (!a)
- return -ENOMEM;
-
- *s = a;
- } else {
- a = message_extend_body(m, 4, 4 + size + 1, false, false);
- if (!a)
- return -ENOMEM;
+ a = message_extend_body(m, 4, 4 + size + 1);
+ if (!a)
+ return -ENOMEM;
- *(uint32_t*) a = size;
- *s = (char*) a + 4;
- }
+ *(uint32_t*) a = size;
+ *s = (char*) a + 4;
(*s)[size] = 0;
struct bus_container *c,
const char *contents,
uint32_t **array_size,
- size_t *begin,
- bool *need_offsets) {
+ size_t *begin) {
unsigned nindex;
- int alignment, r;
+ int alignment;
+ void *a, *op;
+ size_t os;
+ struct bus_body_part *o;
assert(m);
assert(c);
assert(contents);
assert(array_size);
assert(begin);
- assert(need_offsets);
if (!signature_is_single(contents, true))
return -EINVAL;
nindex = e - c->signature;
}
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- alignment = bus_gvariant_get_alignment(contents);
- if (alignment < 0)
- return alignment;
-
- /* Add alignment padding and add to offset list */
- if (!message_extend_body(m, alignment, 0, false, false))
- return -ENOMEM;
-
- r = bus_gvariant_is_fixed_size(contents);
- if (r < 0)
- return r;
-
- *begin = m->body_size;
- *need_offsets = r == 0;
- } else {
- void *a, *op;
- size_t os;
- struct bus_body_part *o;
-
- alignment = bus_type_get_alignment(contents[0]);
- if (alignment < 0)
- return alignment;
+ alignment = bus_type_get_alignment(contents[0]);
+ if (alignment < 0)
+ return alignment;
- a = message_extend_body(m, 4, 4, false, false);
- if (!a)
- return -ENOMEM;
+ a = message_extend_body(m, 4, 4);
+ if (!a)
+ return -ENOMEM;
- o = m->body_end;
- op = m->body_end->data;
- os = m->body_end->size;
+ o = m->body_end;
+ op = m->body_end->data;
+ os = m->body_end->size;
- /* Add alignment between size and first element */
- if (!message_extend_body(m, alignment, 0, false, false))
- return -ENOMEM;
+ /* Add alignment between size and first element */
+ if (!message_extend_body(m, alignment, 0))
+ return -ENOMEM;
- /* location of array size might have changed so let's readjust a */
- if (o == m->body_end)
- a = adjust_pointer(a, op, os, m->body_end->data);
+ /* location of array size might have changed so let's readjust a */
+ if (o == m->body_end)
+ a = adjust_pointer(a, op, os, m->body_end->data);
- *(uint32_t*) a = 0;
- *array_size = a;
- }
+ *(uint32_t*) a = 0;
+ *array_size = a;
if (c->enclosing != SD_BUS_TYPE_ARRAY)
c->index = nindex;
struct bus_container *c,
const char *contents) {
+ size_t l;
+ void *a;
+
assert(m);
assert(c);
assert(contents);
}
}
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- /* Variants are always aligned to 8 */
-
- if (!message_extend_body(m, 8, 0, false, false))
- return -ENOMEM;
-
- } else {
- size_t l;
- void *a;
-
- l = strlen(contents);
- a = message_extend_body(m, 1, 1 + l + 1, false, false);
- if (!a)
- return -ENOMEM;
+ l = strlen(contents);
+ a = message_extend_body(m, 1, 1 + l + 1);
+ if (!a)
+ return -ENOMEM;
- *(uint8_t*) a = l;
- memcpy((uint8_t*) a + 1, contents, l + 1);
- }
+ *(uint8_t*) a = l;
+ memcpy((uint8_t*) a + 1, contents, l + 1);
if (c->enclosing != SD_BUS_TYPE_ARRAY)
c->index++;
sd_bus_message *m,
struct bus_container *c,
const char *contents,
- size_t *begin,
- bool *need_offsets) {
+ size_t *begin) {
size_t nindex;
- int r;
assert(m);
assert(c);
assert(contents);
assert(begin);
- assert(need_offsets);
if (!signature_is_valid(contents, false))
return -EINVAL;
nindex = e - c->signature;
}
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- int alignment;
-
- alignment = bus_gvariant_get_alignment(contents);
- if (alignment < 0)
- return alignment;
-
- if (!message_extend_body(m, alignment, 0, false, false))
- return -ENOMEM;
-
- r = bus_gvariant_is_fixed_size(contents);
- if (r < 0)
- return r;
-
- *begin = m->body_size;
- *need_offsets = r == 0;
- } else {
- /* Align contents to 8 byte boundary */
- if (!message_extend_body(m, 8, 0, false, false))
- return -ENOMEM;
- }
+ /* Align contents to 8 byte boundary */
+ if (!message_extend_body(m, 8, 0))
+ return -ENOMEM;
if (c->enclosing != SD_BUS_TYPE_ARRAY)
c->index = nindex;
sd_bus_message *m,
struct bus_container *c,
const char *contents,
- size_t *begin,
- bool *need_offsets) {
-
- int r;
+ size_t *begin) {
assert(m);
assert(c);
assert(contents);
assert(begin);
- assert(need_offsets);
if (!signature_is_pair(contents))
return -EINVAL;
} else
return -ENXIO;
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- int alignment;
-
- alignment = bus_gvariant_get_alignment(contents);
- if (alignment < 0)
- return alignment;
-
- if (!message_extend_body(m, alignment, 0, false, false))
- return -ENOMEM;
-
- r = bus_gvariant_is_fixed_size(contents);
- if (r < 0)
- return r;
-
- *begin = m->body_size;
- *need_offsets = r == 0;
- } else {
- /* Align contents to 8 byte boundary */
- if (!message_extend_body(m, 8, 0, false, false))
- return -ENOMEM;
- }
+ /* Align contents to 8 byte boundary */
+ if (!message_extend_body(m, 8, 0))
+ return -ENOMEM;
return 0;
}
uint32_t *array_size = NULL;
_cleanup_free_ char *signature = NULL;
size_t before, begin = 0;
- bool need_offsets = false;
int r;
assert_return(m, -EINVAL);
before = m->body_size;
if (type == SD_BUS_TYPE_ARRAY)
- r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
+ r = bus_message_open_array(m, c, contents, &array_size, &begin);
else if (type == SD_BUS_TYPE_VARIANT)
r = bus_message_open_variant(m, c, contents);
else if (type == SD_BUS_TYPE_STRUCT)
- r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
+ r = bus_message_open_struct(m, c, contents, &begin);
else if (type == SD_BUS_TYPE_DICT_ENTRY)
- r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
+ r = bus_message_open_dict_entry(m, c, contents, &begin);
else
r = -EINVAL;
if (r < 0)
.array_size = array_size,
.before = before,
.begin = begin,
- .need_offsets = need_offsets,
};
return 0;
}
-static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
+_public_ int sd_bus_message_close_container(sd_bus_message *m) {
+ struct bus_container *c;
- assert(m);
- assert(c);
+ assert_return(m, -EINVAL);
+ assert_return(!m->sealed, -EPERM);
+ assert_return(m->n_containers > 0, -EINVAL);
+ assert_return(!m->poisoned, -ESTALE);
- if (!BUS_MESSAGE_IS_GVARIANT(m))
- return 0;
+ c = message_get_last_container(m);
- if (c->need_offsets) {
- size_t payload, sz, i;
- uint8_t *a;
+ if (c->enclosing != SD_BUS_TYPE_ARRAY)
+ if (c->signature && c->signature[c->index] != 0)
+ return -EINVAL;
- /* Variable-width arrays */
+ m->n_containers--;
- payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
- sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
+ free(c->signature);
- a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
- if (!a)
- return -ENOMEM;
-
- for (i = 0; i < c->n_offsets; i++)
- bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
- } else {
- void *a;
-
- /* Fixed-width or empty arrays */
-
- a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
- if (!a)
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
- uint8_t *a;
- size_t l;
-
- assert(m);
- assert(c);
- assert(c->signature);
-
- if (!BUS_MESSAGE_IS_GVARIANT(m))
- return 0;
-
- l = strlen(c->signature);
-
- a = message_extend_body(m, 1, 1 + l, true, false);
- if (!a)
- return -ENOMEM;
-
- a[0] = 0;
- memcpy(a+1, c->signature, l);
-
- return 0;
-}
-
-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;
- uint8_t *a;
- int r;
-
- assert(m);
- assert(c);
-
- if (!BUS_MESSAGE_IS_GVARIANT(m))
- return 0;
-
- p = strempty(c->signature);
- while (*p != 0) {
- size_t n;
-
- r = signature_element_length(p, &n);
- if (r < 0)
- return r;
- else {
- char t[n+1];
-
- memcpy(t, p, n);
- t[n] = 0;
-
- r = bus_gvariant_is_fixed_size(t);
- if (r < 0)
- return r;
- }
-
- assert(!c->need_offsets || i <= c->n_offsets);
-
- /* 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++;
-
- i++;
- p += n;
- }
-
- assert(!c->need_offsets || i == c->n_offsets);
- assert(c->need_offsets || 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;
-
- /* 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 {
- size_t sz;
- unsigned j;
-
- assert(c->offsets[c->n_offsets-1] == m->body_size);
-
- sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
-
- a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
- if (!a)
- return -ENOMEM;
-
- p = strempty(c->signature);
- for (i = 0, j = 0; i < c->n_offsets; i++) {
- unsigned k;
- size_t n;
-
- r = signature_element_length(p, &n);
- if (r < 0)
- return r;
- else {
- char t[n+1];
-
- memcpy(t, p, n);
- t[n] = 0;
-
- p += n;
-
- r = bus_gvariant_is_fixed_size(t);
- if (r < 0)
- return r;
- if (r > 0 || p[0] == 0)
- continue;
- }
-
- k = n_variable - 1 - j;
-
- bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
-
- j++;
- }
- }
-
- return 0;
-}
-
-_public_ int sd_bus_message_close_container(sd_bus_message *m) {
- struct bus_container *c;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(m->n_containers > 0, -EINVAL);
- assert_return(!m->poisoned, -ESTALE);
-
- c = message_get_last_container(m);
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- if (c->signature && c->signature[c->index] != 0)
- return -EINVAL;
-
- m->n_containers--;
-
- if (c->enclosing == SD_BUS_TYPE_ARRAY)
- r = bus_message_close_array(m, c);
- else if (c->enclosing == SD_BUS_TYPE_VARIANT)
- r = bus_message_close_variant(m, c);
- else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY))
- r = bus_message_close_struct(m, c, true);
- else
- assert_not_reached();
-
- free(c->signature);
- free(c->offsets);
-
- return r;
-}
+ return 0;
+}
typedef struct {
const char *types;
assert_return(ptr || size == 0, -EINVAL);
assert_return(!m->poisoned, -ESTALE);
- /* alignment and size of the trivial types (except bool) is
- * identical for gvariant and dbus1 marshalling */
align = bus_type_get_alignment(type);
sz = bus_type_get_size(type);
if (r < 0)
return r;
- a = message_extend_body(m, align, size, false, false);
+ a = message_extend_body(m, align, size);
if (!a)
return -ENOMEM;
if (r < 0)
return r;
- a = message_extend_body(m, align, 0, false, false);
+ a = message_extend_body(m, align, 0);
if (!a)
return -ENOMEM;
}
}
- if (!BUS_MESSAGE_IS_GVARIANT(m)) {
- a = message_extend_body(m, 4, 4, false, false);
- if (!a)
- return -ENOMEM;
+ a = message_extend_body(m, 4, 4);
+ if (!a)
+ return -ENOMEM;
- *(uint32_t*) a = size - 1;
- }
+ *(uint32_t*) a = size - 1;
part = message_append_part(m);
if (!part)
m->body_size += size;
message_extend_containers(m, size);
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- r = message_add_offset(m, m->body_size);
- if (r < 0) {
- m->poisoned = true;
- return -ENOMEM;
- }
- }
-
if (c->enclosing != SD_BUS_TYPE_ARRAY)
c->index++;
}
static int bus_message_close_header(sd_bus_message *m) {
-
assert(m);
- /* The actual user data is finished now, we just complete the
- variant and struct now (at least on gvariant). Remember
- this position, so that during parsing we know where to
- put the outer container end. */
+ /* The actual user data is finished now, we just complete the variant and struct now. Remember
+ * this position, so that during parsing we know where to put the outer container end. */
m->user_body_size = m->body_size;
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- const char *signature;
- size_t sz, l;
- void *d;
-
- /* Add offset table to end of fields array */
- if (m->n_header_offsets >= 1) {
- uint8_t *a;
- unsigned i;
-
- assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
-
- sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
- a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
- if (!a)
- return -ENOMEM;
-
- for (i = 0; i < m->n_header_offsets; i++)
- bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
- }
-
- /* Add gvariant NUL byte plus signature to the end of
- * the body, followed by the final offset pointing to
- * the end of the fields array */
-
- signature = strempty(m->root_container.signature);
- l = strlen(signature);
-
- 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 + 2 + sz, false, true);
- if (!d)
- return -ENOMEM;
-
- *(uint8_t*) d = 0;
- *((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 + 2, sz, sizeof(struct bus_header) + m->fields_size);
-
- m->footer = d;
- m->footer_accessible = 1 + l + 2 + sz;
- } else {
- m->header->dbus1.fields_size = m->fields_size;
- m->header->dbus1.body_size = m->body_size;
- }
+ m->header->fields_size = m->fields_size;
+ m->header->body_size = m->body_size;
return 0;
}
if (m->poisoned)
return -ESTALE;
- if (cookie > UINT32_MAX &&
- !BUS_MESSAGE_IS_GVARIANT(m))
+ if (cookie > UINT32_MAX)
return -EOPNOTSUPP;
/* In vtables the return signature of method calls is listed,
!streq(strempty(m->root_container.signature), m->enforced_reply_signature))
return -ENOMSG;
- /* If gvariant marshalling is used we need to close the body structure */
- r = bus_message_close_struct(m, &m->root_container, false);
- if (r < 0)
- return r;
-
- /* If there's a non-trivial signature set, then add it in
- * here, but only on dbus1 */
- if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
+ /* If there's a non-trivial signature set, then add it in here */
+ if (!isempty(m->root_container.signature)) {
r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
if (r < 0)
return r;
if (r < 0)
return r;
- if (BUS_MESSAGE_IS_GVARIANT(m))
- m->header->dbus2.cookie = cookie;
- else
- m->header->dbus1.serial = (uint32_t) cookie;
+ m->header->serial = (uint32_t) cookie;
m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec;
m->root_container.end = m->user_body_size;
m->root_container.index = 0;
- m->root_container.offset_index = 0;
- m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
m->sealed = true;
if (c->enclosing != SD_BUS_TYPE_ARRAY)
return false;
- if (BUS_MESSAGE_IS_GVARIANT(m))
- return index >= c->end;
- else {
- assert(c->array_size);
- return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
- }
+ assert(c->array_size);
+ return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
}
_public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
return NULL;
}
-static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
- int r;
-
- assert(m);
- assert(c);
- assert(rindex);
-
- if (!BUS_MESSAGE_IS_GVARIANT(m))
- return 0;
-
- if (c->enclosing == SD_BUS_TYPE_ARRAY) {
- int sz;
-
- sz = bus_gvariant_get_size(c->signature);
- if (sz == 0)
- return -EBADMSG;
- if (sz < 0) {
- int alignment;
-
- if (c->offset_index+1 >= c->n_offsets)
- goto end;
-
- /* Variable-size array */
-
- alignment = bus_gvariant_get_alignment(c->signature);
- assert(alignment > 0);
-
- *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
- assert(c->offsets[c->offset_index+1] >= *rindex);
- c->item_size = c->offsets[c->offset_index+1] - *rindex;
- } else {
-
- if (c->offset_index+1 >= (c->end-c->begin)/sz)
- goto end;
-
- /* Fixed-size array */
- *rindex = c->begin + (c->offset_index+1) * sz;
- c->item_size = sz;
- }
-
- c->offset_index++;
-
- } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
-
- int alignment;
- size_t n, j;
-
- if (c->offset_index+1 >= c->n_offsets)
- goto end;
-
- r = signature_element_length(c->signature + c->index, &n);
- if (r < 0)
- return r;
-
- r = signature_element_length(c->signature + c->index + n, &j);
- if (r < 0)
- return r;
- else {
- char t[j+1];
- memcpy(t, c->signature + c->index + n, j);
- t[j] = 0;
-
- alignment = bus_gvariant_get_alignment(t);
- }
-
- assert(alignment > 0);
-
- *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
- assert(c->offsets[c->offset_index+1] >= *rindex);
- c->item_size = c->offsets[c->offset_index+1] - *rindex;
-
- c->offset_index++;
-
- } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
- goto end;
- else
- assert_not_reached();
-
- return 0;
-
-end:
- /* Reached the end */
- *rindex = c->end;
- c->item_size = 0;
- return 0;
-}
-
static int message_peek_body(
sd_bus_message *m,
size_t *rindex,
rindex = m->rindex;
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
-
- if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
- bool ok;
-
- /* D-Bus spec: The marshalling formats for the string-like types all end
- * with a single zero (NUL) byte, but that byte is not considered to be part
- * of the text. */
- if (c->item_size == 0)
- return -EBADMSG;
-
- r = message_peek_body(m, &rindex, 1, c->item_size, &q);
- if (r < 0)
- return r;
-
- if (type == SD_BUS_TYPE_STRING)
- ok = validate_string(q, c->item_size-1);
- else if (type == SD_BUS_TYPE_OBJECT_PATH)
- ok = validate_object_path(q, c->item_size-1);
- else
- ok = validate_signature(q, c->item_size-1);
-
- if (!ok)
- return -EBADMSG;
+ if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
+ uint32_t l;
+ bool ok;
- if (p)
- *(const char**) p = q;
- } else {
- int sz, align;
+ r = message_peek_body(m, &rindex, 4, 4, &q);
+ if (r < 0)
+ return r;
- sz = bus_gvariant_get_size(CHAR_TO_STR(type));
- assert(sz > 0);
- if ((size_t) sz != c->item_size)
- return -EBADMSG;
+ l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
+ if (l == UINT32_MAX)
+ /* avoid overflow right below */
+ return -EBADMSG;
- align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
- assert(align > 0);
+ r = message_peek_body(m, &rindex, 1, l+1, &q);
+ if (r < 0)
+ return r;
- r = message_peek_body(m, &rindex, align, c->item_size, &q);
- if (r < 0)
- return r;
+ if (type == SD_BUS_TYPE_OBJECT_PATH)
+ ok = validate_object_path(q, l);
+ else
+ ok = validate_string(q, l);
+ if (!ok)
+ return -EBADMSG;
- switch (type) {
+ if (p)
+ *(const char**) p = q;
- case SD_BUS_TYPE_BYTE:
- if (p)
- *(uint8_t*) p = *(uint8_t*) q;
- break;
+ } else if (type == SD_BUS_TYPE_SIGNATURE) {
+ uint8_t l;
- case SD_BUS_TYPE_BOOLEAN:
- if (p)
- *(int*) p = !!*(uint8_t*) q;
- break;
-
- case SD_BUS_TYPE_INT16:
- case SD_BUS_TYPE_UINT16:
- if (p)
- *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
- break;
+ r = message_peek_body(m, &rindex, 1, 1, &q);
+ if (r < 0)
+ return r;
- case SD_BUS_TYPE_INT32:
- case SD_BUS_TYPE_UINT32:
- if (p)
- *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
- break;
+ l = *(uint8_t*) q;
+ if (l == UINT8_MAX)
+ /* avoid overflow right below */
+ return -EBADMSG;
- case SD_BUS_TYPE_INT64:
- case SD_BUS_TYPE_UINT64:
- case SD_BUS_TYPE_DOUBLE:
- if (p)
- *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
- break;
+ r = message_peek_body(m, &rindex, 1, l+1, &q);
+ if (r < 0)
+ return r;
- case SD_BUS_TYPE_UNIX_FD: {
- uint32_t j;
+ if (!validate_signature(q, l))
+ return -EBADMSG;
- j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
- if (j >= m->n_fds)
- return -EBADMSG;
+ if (p)
+ *(const char**) p = q;
- if (p)
- *(int*) p = m->fds[j];
+ } else {
+ ssize_t sz, align;
- break;
- }
+ align = bus_type_get_alignment(type);
+ assert(align > 0);
- default:
- assert_not_reached();
- }
- }
+ sz = bus_type_get_size(type);
+ assert(sz > 0);
- r = container_next_item(m, c, &rindex);
+ r = message_peek_body(m, &rindex, align, sz, &q);
if (r < 0)
return r;
- } else {
-
- if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
- uint32_t l;
- bool ok;
- r = message_peek_body(m, &rindex, 4, 4, &q);
- if (r < 0)
- return r;
-
- l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
- if (l == UINT32_MAX)
- /* avoid overflow right below */
- return -EBADMSG;
-
- r = message_peek_body(m, &rindex, 1, l+1, &q);
- if (r < 0)
- return r;
+ switch (type) {
- if (type == SD_BUS_TYPE_OBJECT_PATH)
- ok = validate_object_path(q, l);
- else
- ok = validate_string(q, l);
- if (!ok)
- return -EBADMSG;
+ case SD_BUS_TYPE_BYTE:
+ if (p)
+ *(uint8_t*) p = *(uint8_t*) q;
+ break;
+ case SD_BUS_TYPE_BOOLEAN:
if (p)
- *(const char**) p = q;
+ *(int*) p = !!*(uint32_t*) q;
+ break;
- } else if (type == SD_BUS_TYPE_SIGNATURE) {
- uint8_t l;
+ case SD_BUS_TYPE_INT16:
+ case SD_BUS_TYPE_UINT16:
+ if (p)
+ *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
+ break;
- r = message_peek_body(m, &rindex, 1, 1, &q);
- if (r < 0)
- return r;
+ case SD_BUS_TYPE_INT32:
+ case SD_BUS_TYPE_UINT32:
+ if (p)
+ *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
+ break;
- l = *(uint8_t*) q;
- if (l == UINT8_MAX)
- /* avoid overflow right below */
- return -EBADMSG;
+ case SD_BUS_TYPE_INT64:
+ case SD_BUS_TYPE_UINT64:
+ case SD_BUS_TYPE_DOUBLE:
+ if (p)
+ *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
+ break;
- r = message_peek_body(m, &rindex, 1, l+1, &q);
- if (r < 0)
- return r;
+ case SD_BUS_TYPE_UNIX_FD: {
+ uint32_t j;
- if (!validate_signature(q, l))
+ j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
+ if (j >= m->n_fds)
return -EBADMSG;
if (p)
- *(const char**) p = q;
-
- } else {
- ssize_t sz, align;
-
- align = bus_type_get_alignment(type);
- assert(align > 0);
-
- sz = bus_type_get_size(type);
- assert(sz > 0);
-
- r = message_peek_body(m, &rindex, align, sz, &q);
- if (r < 0)
- return r;
-
- switch (type) {
-
- case SD_BUS_TYPE_BYTE:
- if (p)
- *(uint8_t*) p = *(uint8_t*) q;
- break;
-
- case SD_BUS_TYPE_BOOLEAN:
- if (p)
- *(int*) p = !!*(uint32_t*) q;
- break;
-
- case SD_BUS_TYPE_INT16:
- case SD_BUS_TYPE_UINT16:
- if (p)
- *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
- break;
-
- case SD_BUS_TYPE_INT32:
- case SD_BUS_TYPE_UINT32:
- if (p)
- *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
- break;
-
- case SD_BUS_TYPE_INT64:
- case SD_BUS_TYPE_UINT64:
- case SD_BUS_TYPE_DOUBLE:
- if (p)
- *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
- break;
-
- case SD_BUS_TYPE_UNIX_FD: {
- uint32_t j;
-
- j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
- if (j >= m->n_fds)
- return -EBADMSG;
-
- if (p)
- *(int*) p = m->fds[j];
- break;
- }
+ *(int*) p = m->fds[j];
+ break;
+ }
- default:
- assert_not_reached();
- }
+ default:
+ assert_not_reached();
}
}
sd_bus_message *m,
struct bus_container *c,
const char *contents,
- uint32_t **array_size,
- size_t *item_size,
- size_t **offsets,
- size_t *n_offsets) {
+ uint32_t **array_size) {
size_t rindex;
void *q;
- int r;
+ int alignment, r;
assert(m);
assert(c);
assert(contents);
assert(array_size);
- assert(item_size);
- assert(offsets);
- assert(n_offsets);
if (!signature_is_single(contents, true))
return -EINVAL;
rindex = m->rindex;
- if (!BUS_MESSAGE_IS_GVARIANT(m)) {
- /* dbus1 */
- int alignment;
-
- r = message_peek_body(m, &rindex, 4, 4, &q);
- if (r < 0)
- return r;
-
- if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
- return -EBADMSG;
-
- alignment = bus_type_get_alignment(contents[0]);
- if (alignment < 0)
- return alignment;
-
- r = message_peek_body(m, &rindex, alignment, 0, NULL);
- if (r < 0)
- return r;
-
- *array_size = (uint32_t*) q;
-
- } else if (c->item_size <= 0) {
-
- /* gvariant: empty array */
- *item_size = 0;
- *offsets = NULL;
- *n_offsets = 0;
-
- } else if (bus_gvariant_is_fixed_size(contents)) {
-
- /* gvariant: fixed length array */
- *item_size = bus_gvariant_get_size(contents);
- *offsets = NULL;
- *n_offsets = 0;
-
- } else {
- size_t where, previous = 0, framing, sz;
- int alignment;
- unsigned i;
-
- /* gvariant: variable length array */
- sz = bus_gvariant_determine_word_size(c->item_size, 0);
-
- where = rindex + c->item_size - sz;
- r = message_peek_body(m, &where, 1, sz, &q);
- if (r < 0)
- return r;
-
- framing = bus_gvariant_read_word_le(q, sz);
- if (framing > c->item_size - sz)
- return -EBADMSG;
- if ((c->item_size - framing) % sz != 0)
- return -EBADMSG;
-
- *n_offsets = (c->item_size - framing) / sz;
-
- where = rindex + framing;
- r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
- if (r < 0)
- return r;
-
- *offsets = new(size_t, *n_offsets);
- if (!*offsets)
- return -ENOMEM;
-
- alignment = bus_gvariant_get_alignment(c->signature);
- assert(alignment > 0);
-
- for (i = 0; i < *n_offsets; i++) {
- size_t x, start;
-
- start = ALIGN_TO(previous, alignment);
-
- x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
- if (x > c->item_size - sz)
- return -EBADMSG;
- if (x < start)
- return -EBADMSG;
-
- (*offsets)[i] = rindex + x;
- previous = x;
- }
-
- *item_size = (*offsets)[0] - rindex;
- }
-
- m->rindex = rindex;
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- c->index += 1 + strlen(contents);
-
- return 1;
-}
-
-static int bus_message_enter_variant(
- sd_bus_message *m,
- struct bus_container *c,
- const char *contents,
- size_t *item_size) {
-
- size_t rindex;
- uint8_t l;
- void *q;
- int r;
-
- assert(m);
- assert(c);
- assert(contents);
- assert(item_size);
-
- if (!signature_is_single(contents, false))
- return -EINVAL;
-
- if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
- return -EINVAL;
-
- if (!c->signature || c->signature[c->index] == 0)
- return -ENXIO;
-
- if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
- return -ENXIO;
-
- rindex = m->rindex;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- size_t k, where;
-
- k = strlen(contents);
- if (1+k > c->item_size)
- return -EBADMSG;
-
- where = rindex + c->item_size - (1+k);
- r = message_peek_body(m, &where, 1, 1+k, &q);
- if (r < 0)
- return r;
-
- if (*(char*) q != 0)
- return -EBADMSG;
-
- if (memcmp((uint8_t*) q+1, contents, k))
- return -ENXIO;
-
- *item_size = c->item_size - (1+k);
-
- } else {
- r = message_peek_body(m, &rindex, 1, 1, &q);
- if (r < 0)
- return r;
-
- l = *(uint8_t*) q;
- if (l == UINT8_MAX)
- /* avoid overflow right below */
- return -EBADMSG;
-
- r = message_peek_body(m, &rindex, 1, l+1, &q);
- if (r < 0)
- return r;
-
- if (!validate_signature(q, l))
- return -EBADMSG;
-
- if (!streq(q, contents))
- return -ENXIO;
- }
-
- m->rindex = rindex;
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- c->index++;
-
- return 1;
-}
-
-static int build_struct_offsets(
- sd_bus_message *m,
- const char *signature,
- size_t size,
- size_t *item_size,
- size_t **offsets,
- size_t *n_offsets) {
-
- unsigned n_variable = 0, n_total = 0, v;
- size_t previous, where;
- const char *p;
- size_t sz;
- void *q;
- int r;
-
- assert(m);
- assert(item_size);
- assert(offsets);
- assert(n_offsets);
-
- 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;
- *offsets = NULL;
- *n_offsets = 0;
- return 0;
- }
+ r = message_peek_body(m, &rindex, 4, 4, &q);
+ if (r < 0)
+ return r;
- sz = bus_gvariant_determine_word_size(size, 0);
- if (sz <= 0)
+ if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
return -EBADMSG;
- /* First, loop over signature and count variable elements and
- * elements in general. We use this to know how large the
- * offset array is at the end of the structure. Note that
- * GVariant only stores offsets for all variable size elements
- * that are not the last item. */
-
- p = signature;
- while (*p != 0) {
- size_t n;
-
- r = signature_element_length(p, &n);
- if (r < 0)
- return r;
- else {
- char t[n+1];
-
- memcpy(t, p, n);
- t[n] = 0;
-
- r = bus_gvariant_is_fixed_size(t);
- }
-
- if (r < 0)
- return r;
- if (r == 0 && p[n] != 0) /* except the last item */
- n_variable++;
- n_total++;
-
- p += n;
- }
-
- if (size < n_variable * sz)
- return -EBADMSG;
+ alignment = bus_type_get_alignment(contents[0]);
+ if (alignment < 0)
+ return alignment;
- where = m->rindex + size - (n_variable * sz);
- r = message_peek_body(m, &where, 1, n_variable * sz, &q);
+ r = message_peek_body(m, &rindex, alignment, 0, NULL);
if (r < 0)
return r;
- v = n_variable;
-
- *offsets = new(size_t, n_total);
- if (!*offsets)
- return -ENOMEM;
-
- *n_offsets = 0;
+ *array_size = (uint32_t*) q;
- /* Second, loop again and build an offset table */
- p = signature;
- previous = m->rindex;
- while (*p != 0) {
- size_t n, offset;
- int k;
-
- r = signature_element_length(p, &n);
- if (r < 0)
- return r;
- else {
- char t[n+1];
-
- memcpy(t, p, n);
- t[n] = 0;
-
- size_t align = bus_gvariant_get_alignment(t);
- assert(align > 0);
-
- /* The possible start of this member after including alignment */
- size_t start = ALIGN_TO(previous, align);
-
- k = bus_gvariant_get_size(t);
- if (k < 0) {
- size_t x;
-
- /* Variable size */
- if (v > 0) {
- v--;
-
- x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
- if (x >= size)
- return -EBADMSG;
- } else
- /* The last item's end is determined
- * from the start of the offset array */
- x = size - (n_variable * sz);
-
- offset = m->rindex + x;
- if (offset < start)
- return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
- "For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu",
- t, align,
- offset,
- previous,
- start);
- } else
- /* Fixed size */
- offset = start + k;
- }
-
- previous = (*offsets)[(*n_offsets)++] = offset;
- p += n;
- }
+ m->rindex = rindex;
- assert(v == 0);
- assert(*n_offsets == n_total);
+ if (c->enclosing != SD_BUS_TYPE_ARRAY)
+ c->index += 1 + strlen(contents);
- *item_size = (*offsets)[0] - m->rindex;
- return 0;
+ return 1;
}
-static int enter_struct_or_dict_entry(
+static int bus_message_enter_variant(
sd_bus_message *m,
struct bus_container *c,
- const char *contents,
- size_t *item_size,
- size_t **offsets,
- size_t *n_offsets) {
+ const char *contents) {
+ size_t rindex;
+ uint8_t l;
+ void *q;
int r;
assert(m);
assert(c);
assert(contents);
- assert(item_size);
- assert(offsets);
- assert(n_offsets);
- if (!BUS_MESSAGE_IS_GVARIANT(m)) {
+ if (!signature_is_single(contents, false))
+ return -EINVAL;
- /* dbus1 */
- r = message_peek_body(m, &m->rindex, 8, 0, NULL);
- if (r < 0)
- return r;
+ if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
+ return -EINVAL;
- } else
- /* gvariant with contents */
- return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
+ if (!c->signature || c->signature[c->index] == 0)
+ return -ENXIO;
- return 0;
+ if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
+ return -ENXIO;
+
+ rindex = m->rindex;
+
+ r = message_peek_body(m, &rindex, 1, 1, &q);
+ if (r < 0)
+ return r;
+
+ l = *(uint8_t*) q;
+ if (l == UINT8_MAX)
+ /* avoid overflow right below */
+ return -EBADMSG;
+
+ r = message_peek_body(m, &rindex, 1, l+1, &q);
+ if (r < 0)
+ return r;
+
+ if (!validate_signature(q, l))
+ return -EBADMSG;
+
+ if (!streq(q, contents))
+ return -ENXIO;
+
+ m->rindex = rindex;
+
+ if (c->enclosing != SD_BUS_TYPE_ARRAY)
+ c->index++;
+
+ return 1;
}
static int bus_message_enter_struct(
sd_bus_message *m,
struct bus_container *c,
- const char *contents,
- size_t *item_size,
- size_t **offsets,
- size_t *n_offsets) {
+ const char *contents) {
size_t l;
int r;
assert(m);
assert(c);
assert(contents);
- assert(item_size);
- assert(offsets);
- assert(n_offsets);
if (!signature_is_valid(contents, false))
return -EINVAL;
c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
return -ENXIO;
- r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
+ r = message_peek_body(m, &m->rindex, 8, 0, NULL);
if (r < 0)
return r;
static int bus_message_enter_dict_entry(
sd_bus_message *m,
struct bus_container *c,
- const char *contents,
- size_t *item_size,
- size_t **offsets,
- size_t *n_offsets) {
+ const char *contents) {
size_t l;
int r;
c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
return -ENXIO;
- r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
+ r = message_peek_body(m, &m->rindex, 8, 0, NULL);
if (r < 0)
return r;
struct bus_container *c;
uint32_t *array_size = NULL;
_cleanup_free_ char *signature = NULL;
- size_t before, end;
- _cleanup_free_ size_t *offsets = NULL;
- size_t n_offsets = 0, item_size = 0;
+ size_t before;
int r;
assert_return(m, -EINVAL);
before = m->rindex;
if (type == SD_BUS_TYPE_ARRAY)
- r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
+ r = bus_message_enter_array(m, c, contents, &array_size);
else if (type == SD_BUS_TYPE_VARIANT)
- r = bus_message_enter_variant(m, c, contents, &item_size);
+ r = bus_message_enter_variant(m, c, contents);
else if (type == SD_BUS_TYPE_STRUCT)
- r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
+ r = bus_message_enter_struct(m, c, contents);
else if (type == SD_BUS_TYPE_DICT_ENTRY)
- r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
+ r = bus_message_enter_dict_entry(m, c, contents);
else
r = -EINVAL;
if (r <= 0)
return r;
/* OK, let's fill it in */
- if (BUS_MESSAGE_IS_GVARIANT(m) &&
- type == SD_BUS_TYPE_STRUCT &&
- isempty(signature))
- end = m->rindex + 0;
- else
- end = m->rindex + c->item_size;
-
m->containers[m->n_containers++] = (struct bus_container) {
.enclosing = type,
.signature = TAKE_PTR(signature),
.before = before,
.begin = m->rindex,
/* Unary type has fixed size of 1, but virtual size of 0 */
- .end = end,
+ .end = m->rindex,
.array_size = array_size,
- .item_size = item_size,
- .offsets = TAKE_PTR(offsets),
- .n_offsets = n_offsets,
};
return 1;
_public_ int sd_bus_message_exit_container(sd_bus_message *m) {
struct bus_container *c;
- unsigned saved;
- int r;
assert_return(m, -EINVAL);
assert_return(m->sealed, -EPERM);
return -EBUSY;
}
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- if (m->rindex < c->end)
- return -EBUSY;
-
- } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
+ if (c->enclosing == SD_BUS_TYPE_ARRAY) {
uint32_t l;
l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
message_free_last_container(m);
- c = message_get_last_container(m);
- saved = c->index;
- c->index = c->saved_index;
- r = container_next_item(m, c, &m->rindex);
- c->index = saved;
- if (r < 0)
- return r;
-
return 1;
}
if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
if (contents) {
+ size_t rindex, l;
void *q;
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- size_t k;
-
- if (c->item_size < 2)
- return -EBADMSG;
-
- /* Look for the NUL delimiter that
- separates the payload from the
- signature. Since the body might be
- in a different part that then the
- signature we map byte by byte. */
-
- for (k = 2; k <= c->item_size; k++) {
- size_t where;
-
- where = m->rindex + c->item_size - k;
- r = message_peek_body(m, &where, 1, k, &q);
- if (r < 0)
- return r;
-
- if (*(char*) q == 0)
- break;
- }
-
- if (k > c->item_size)
- return -EBADMSG;
-
- if (free_and_strndup(&c->peeked_signature,
- (char*) q + 1, k - 1) < 0)
- return -ENOMEM;
-
- if (!signature_is_valid(c->peeked_signature, true))
- return -EBADMSG;
-
- *contents = c->peeked_signature;
- } else {
- size_t rindex, l;
-
- rindex = m->rindex;
- r = message_peek_body(m, &rindex, 1, 1, &q);
- if (r < 0)
- return r;
+ rindex = m->rindex;
+ r = message_peek_body(m, &rindex, 1, 1, &q);
+ if (r < 0)
+ return r;
- l = *(uint8_t*) q;
- if (l == UINT8_MAX)
- /* avoid overflow right below */
- return -EBADMSG;
+ l = *(uint8_t*) q;
+ if (l == UINT8_MAX)
+ /* avoid overflow right below */
+ return -EBADMSG;
- r = message_peek_body(m, &rindex, 1, l+1, &q);
- if (r < 0)
- return r;
+ r = message_peek_body(m, &rindex, 1, l+1, &q);
+ if (r < 0)
+ return r;
- if (!validate_signature(q, l))
- return -EBADMSG;
+ if (!validate_signature(q, l))
+ return -EBADMSG;
- *contents = q;
- }
+ *contents = q;
}
if (type)
m->rindex = c->begin;
}
- c->offset_index = 0;
- c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
-
return !isempty(c->signature);
}
c = message_get_last_container(m);
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
- if (align < 0)
- return align;
-
- sz = c->end - c->begin;
- } else {
- align = bus_type_get_alignment(type);
- if (align < 0)
- return align;
+ align = bus_type_get_alignment(type);
+ if (align < 0)
+ return align;
- sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
- }
+ sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
if (sz == 0)
/* Zero length array, let's return some aligned
assert(m);
assert(ri);
- if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
- return -EBADMSG;
-
- /* identical for gvariant and dbus1 */
-
r = message_peek_fields(m, ri, 4, 4, &q);
if (r < 0)
return r;
return 0;
}
-static int message_peek_field_uint64(
- sd_bus_message *m,
- size_t *ri,
- size_t item_size,
- uint64_t *ret) {
-
- int r;
- void *q;
-
- assert(m);
- assert(ri);
-
- if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
- return -EBADMSG;
-
- /* identical for gvariant and dbus1 */
-
- r = message_peek_fields(m, ri, 8, 8, &q);
- if (r < 0)
- return r;
-
- if (ret)
- *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
-
- return 0;
-}
-
static int message_peek_field_string(
sd_bus_message *m,
bool (*validate)(const char *p),
assert(m);
assert(ri);
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
-
- if (item_size <= 0)
- return -EBADMSG;
-
- r = message_peek_fields(m, ri, 1, item_size, &q);
- if (r < 0)
- return r;
-
- l = item_size - 1;
- } else {
- r = message_peek_field_uint32(m, ri, 4, &l);
- if (r < 0)
- return r;
+ r = message_peek_field_uint32(m, ri, 4, &l);
+ if (r < 0)
+ return r;
- if (l == UINT32_MAX)
- /* avoid overflow right below */
- return -EBADMSG;
+ if (l == UINT32_MAX)
+ /* avoid overflow right below */
+ return -EBADMSG;
- r = message_peek_fields(m, ri, 1, l+1, &q);
- if (r < 0)
- return r;
- }
+ r = message_peek_fields(m, ri, 1, l+1, &q);
+ if (r < 0)
+ return r;
if (validate) {
if (!validate_nul(q, l))
assert(m);
assert(ri);
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
-
- if (item_size <= 0)
- return -EBADMSG;
-
- r = message_peek_fields(m, ri, 1, item_size, &q);
- if (r < 0)
- return r;
-
- l = item_size - 1;
- } else {
- r = message_peek_fields(m, ri, 1, 1, &q);
- if (r < 0)
- return r;
+ r = message_peek_fields(m, ri, 1, 1, &q);
+ if (r < 0)
+ return r;
- l = *(uint8_t*) q;
- if (l == UINT8_MAX)
- /* avoid overflow right below */
- return -EBADMSG;
+ l = *(uint8_t*) q;
+ if (l == UINT8_MAX)
+ /* avoid overflow right below */
+ return -EBADMSG;
- r = message_peek_fields(m, ri, 1, l+1, &q);
- if (r < 0)
- return r;
- }
+ r = message_peek_fields(m, ri, 1, l+1, &q);
+ if (r < 0)
+ return r;
if (!validate_signature(q, l))
return -EBADMSG;
assert(m);
assert(ri);
assert(signature);
- assert(!BUS_MESSAGE_IS_GVARIANT(m));
original_index = *ri;
}
static int message_parse_fields(sd_bus_message *m) {
- size_t ri;
- int r;
uint32_t unix_fds = 0;
bool unix_fds_set = false;
- void *offsets = NULL;
- unsigned n_offsets = 0;
- size_t sz = 0;
- unsigned i = 0;
+ int r;
assert(m);
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- char *p;
-
- /* Read the signature from the end of the body variant first */
- sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
- if (m->footer_accessible < 1 + sz)
- return -EBADMSG;
-
- p = (char*) m->footer + m->footer_accessible - (1 + sz);
- for (;;) {
- if (p < (char*) m->footer)
- return -EBADMSG;
-
- if (*p == 0) {
- _cleanup_free_ char *k = NULL;
- size_t l;
-
- /* 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. */
-
- 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;
-
- k = memdup_suffix0(p + 1 + 1, l - 2);
- if (!k)
- return -ENOMEM;
-
- if (!signature_is_valid(k, true))
- return -EBADMSG;
-
- free_and_replace(m->root_container.signature, k);
- break;
- }
-
- p--;
- }
-
- /* Calculate the actual user body size, by removing
- * the trailing variant signature and struct offset
- * table */
- m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
-
- /* Pull out the offset table for the fields array, if any */
- if (m->fields_size > 0) {
- sz = bus_gvariant_determine_word_size(m->fields_size, 0);
- if (sz > 0) {
- size_t framing;
- void *q;
-
- if (m->fields_size < sz)
- return -EBADMSG;
-
- ri = m->fields_size - sz;
- r = message_peek_fields(m, &ri, 1, sz, &q);
- if (r < 0)
- return r;
-
- framing = bus_gvariant_read_word_le(q, sz);
- if (framing >= m->fields_size - sz)
- return -EBADMSG;
- if ((m->fields_size - framing) % sz != 0)
- return -EBADMSG;
-
- ri = framing;
- r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
- if (r < 0)
- return r;
-
- n_offsets = (m->fields_size - framing) / sz;
- }
- }
- } else
- m->user_body_size = m->body_size;
+ m->user_body_size = m->body_size;
- ri = 0;
- while (ri < m->fields_size) {
- _cleanup_free_ char *sig = NULL;
+ for (size_t ri = 0; ri < m->fields_size; ) {
const char *signature;
uint64_t field_type;
size_t item_size = SIZE_MAX;
+ uint8_t *u8;
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- uint64_t *u64;
-
- if (i >= n_offsets)
- break;
-
- if (i == 0)
- ri = 0;
- else
- ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
-
- r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
- if (r < 0)
- return r;
-
- field_type = BUS_MESSAGE_BSWAP64(m, *u64);
- } else {
- uint8_t *u8;
-
- r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
- if (r < 0)
- return r;
-
- field_type = *u8;
- }
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- size_t where, end;
- char *b;
- void *q;
-
- end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
-
- if (end < ri)
- return -EBADMSG;
-
- where = ri = ALIGN_TO(ri, 8);
- item_size = end - ri;
- r = message_peek_fields(m, &where, 1, item_size, &q);
- if (r < 0)
- return r;
-
- b = memrchr(q, 0, item_size);
- if (!b)
- return -EBADMSG;
+ r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
+ if (r < 0)
+ return r;
- sig = memdup_suffix0(b+1, item_size - (b+1-(char*) q));
- if (!sig)
- return -ENOMEM;
+ field_type = *u8;
- signature = sig;
- item_size = b - (char*) q;
- } else {
- r = message_peek_field_signature(m, &ri, 0, &signature);
- if (r < 0)
- return r;
- }
+ r = message_peek_field_signature(m, &ri, 0, &signature);
+ if (r < 0)
+ return r;
switch (field_type) {
const char *s;
char *c;
- if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
- return -EBADMSG;
-
if (m->root_container.signature)
return -EBADMSG;
break;
}
- case BUS_MESSAGE_HEADER_REPLY_SERIAL:
+ case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
+ uint32_t serial;
if (m->reply_cookie != 0)
return -EBADMSG;
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- /* 64bit on dbus2 */
-
- if (!streq(signature, "t"))
- return -EBADMSG;
-
- r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
- if (r < 0)
- return r;
- } else {
- /* 32bit on dbus1 */
- uint32_t serial;
- if (!streq(signature, "u"))
- return -EBADMSG;
+ if (!streq(signature, "u"))
+ return -EBADMSG;
- r = message_peek_field_uint32(m, &ri, item_size, &serial);
- if (r < 0)
- return r;
+ r = message_peek_field_uint32(m, &ri, item_size, &serial);
+ if (r < 0)
+ return r;
- m->reply_cookie = serial;
- }
+ m->reply_cookie = serial;
if (m->reply_cookie == 0)
return -EBADMSG;
break;
-
+ }
case BUS_MESSAGE_HEADER_UNIX_FDS:
if (unix_fds_set)
return -EBADMSG;
break;
default:
- if (!BUS_MESSAGE_IS_GVARIANT(m))
- r = message_skip_fields(m, &ri, UINT32_MAX, (const char **) &signature);
+ r = message_skip_fields(m, &ri, UINT32_MAX, (const char **) &signature);
}
-
if (r < 0)
return r;
-
- i++;
}
if (m->n_fds != unix_fds)
m->root_container.end = m->user_body_size;
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- r = build_struct_offsets(
- m,
- m->root_container.signature,
- m->user_body_size,
- &m->root_container.item_size,
- &m->root_container.offsets,
- &m->root_container.n_offsets);
- if (r == -EINVAL)
- return -EBADMSG;
- if (r < 0)
- return r;
- }
-
/* Try to read the error message, but if we can't it's a non-issue */
if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
(void) sd_bus_message_read(m, "s", &m->error.message);