summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dbus/dbus-marshal-gvariant.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/dbus/dbus-marshal-gvariant.c b/dbus/dbus-marshal-gvariant.c
index ef0f88be..ebd07fea 100644
--- a/dbus/dbus-marshal-gvariant.c
+++ b/dbus/dbus-marshal-gvariant.c
@@ -34,6 +34,9 @@
/** Static #DBusString containing the signature of a message header */
_DBUS_STRING_DEFINE_STATIC(_dbus_header_gvariant_signature_str, DBUS_HEADER_GVARIANT_SIGNATURE);
+static int
+_dbus_reader_get_signature_fixed_size (const DBusString *signature, int *pos, int *alignment, int depth);
+
#define FIELD_ID_SIZE sizeof(dbus_uint64_t)
const DBusString *
@@ -789,7 +792,24 @@ _dbus_message_finalize_gvariant (DBusMessage *message, dbus_bool_t remove_signat
* and delete the field
*/
const char *sig_ptr = _dbus_string_get_const_data (type_str) + type_pos;
+ int alignment;
+ int fixed_size;
+
_dbus_string_init_const (&str, sig_ptr);
+
+ /* There is a special case for structs of fixed size. They need to have size
+ * which is a multiply of required alignment.
+ * The root struct must be finalized just before adding signature and locking the message.
+ * Luckily, fixed size means that there are no offsets in the message body.
+ */
+ fixed_size = _dbus_reader_get_signature_fixed_size (type_str, &type_pos, &alignment, 1);
+ if (fixed_size > 0)
+ {
+ int current_length = _dbus_string_get_length (&message->body);
+ int diff = _DBUS_ALIGN_VALUE (current_length, alignment) - current_length;
+ if (diff > 0)
+ _dbus_string_insert_bytes (&message->body, current_length, diff, 0);
+ }
}
else
{
@@ -845,17 +865,18 @@ update_size (int current_size, int size_of_element, int *alignment, int new_alig
}
static int
-_dbus_reader_get_signature_fixed_size (const DBusString *signature, int *pos, int *alignment)
+_dbus_reader_get_signature_fixed_size (const DBusString *signature, int *pos, int *alignment,
+ int depth)
{
int res = 0;
- int depth = 0;
int current_alignment = 1;
dbus_bool_t variable = FALSE;
+ int length = _dbus_string_get_length (signature);
char c = _dbus_string_get_byte (signature, *pos);
if (c == DBUS_STRUCT_BEGIN_CHAR || c == DBUS_DICT_ENTRY_BEGIN_CHAR)
{
- depth = 1;
+ depth++;
(*pos)++;
}
@@ -888,7 +909,7 @@ _dbus_reader_get_signature_fixed_size (const DBusString *signature, int *pos, in
case DBUS_DICT_ENTRY_BEGIN_CHAR:
{
int alignment_recursive;
- int res_recursive = _dbus_reader_get_signature_fixed_size (signature, pos, &alignment_recursive);
+ int res_recursive = _dbus_reader_get_signature_fixed_size (signature, pos, &alignment_recursive, 0);
if (res_recursive == 0)
variable = TRUE; /* variable size detected */
@@ -904,7 +925,7 @@ _dbus_reader_get_signature_fixed_size (const DBusString *signature, int *pos, in
{
int alignment_recursive;
int recursive_pos = *pos + 1;
- int res_recursive = _dbus_reader_get_signature_fixed_size (signature, &recursive_pos, &alignment_recursive);
+ int res_recursive = _dbus_reader_get_signature_fixed_size (signature, &recursive_pos, &alignment_recursive, 0);
variable = TRUE; /* variable size detected */
@@ -915,11 +936,14 @@ _dbus_reader_get_signature_fixed_size (const DBusString *signature, int *pos, in
*pos = recursive_pos - 1;
}
break;
+ case DBUS_TYPE_INVALID:
+ depth = 0;
+ break;
default:
variable = TRUE; /* variable size detected */
}
(*pos)++;
- } while (depth > 0);
+ } while (depth > 0 && *pos < length);
/* we want to point it to the last character, to allow upper instance to skip it */
(*pos)--;
@@ -934,13 +958,13 @@ int
_dbus_reader_get_type_fixed_size (DBusTypeReader *reader, int *alignment)
{
int pos = reader->type_pos;
- return _dbus_reader_get_signature_fixed_size (reader->type_str, &pos, alignment);
+ return _dbus_reader_get_signature_fixed_size (reader->type_str, &pos, alignment, 0);
}
int
_dbus_type_gvariant_get_fixed_size (const DBusString *type_str, int type_pos, int *alignment)
{
- return _dbus_reader_get_signature_fixed_size (type_str, &type_pos, alignment);
+ return _dbus_reader_get_signature_fixed_size (type_str, &type_pos, alignment, 0);
}
static int