diff options
-rw-r--r-- | dbus/dbus-marshal-gvariant.c | 40 |
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 |