With GVariant, we had to do a trade-off. libdbus API does not provide
any function that would state that a message is "finished".
While creating dbus-1 messages, they are always complete.
On additions header fields can change, and all the data is simply
appended. With GVariant it is different. The format does not have
signature field anymore in the header, but it is at the end
of a message, as a part of body variant. After a body variant,
there is also a body offset appended. These values are added to a body
when a message is considered "finished". We have chosen function
dbus_message_lock() as a signal that a message is finished.
This function is always called when a message is added to output queue.
Now, what does actually happen in case of immediate iteration after
creating a message with empty body? The length of the body is zero.
This is not possible for valid GVariant as it has at least one NUL byte,
signature (minimal is '()') and a body offset. It breaks
_dbus_message_gvariant_get_body_length(). However, it can be done with
public interface, therefore this patch:
1. fixes _dbus_message_gvariant_get_body_length() to return 0 in case
of empty body, instead of computing "negative" value.
2. warns users when they try to iterate over a GVariant message
that is not locked.
Change-Id: Ie7dc331f5ea278502df02a976e555a2c7d249197
{
size_t body_len = _dbus_string_get_length (&message->body);
size_t message_len = body_len + _dbus_string_get_length (&message->header.data);
- body_len -= bus_gvariant_determine_word_size (message_len , 0);
+ size_t offset_size = bus_gvariant_determine_word_size (message_len, 0);
+ if (body_len <= offset_size)
+ return 0;
+
+ body_len -= offset_size;
+
+ /* searching for variant's NULL byte */
while (body_len > 0 && _dbus_string_get_byte (&message->body, body_len) != 0)
body_len--;
_dbus_type_reader_gvariant_init (DBusTypeReader *reader,
DBusMessage *message)
{
+#ifndef DBUS_DISABLE_CHECKS
+ if (!message->locked)
+ _dbus_warn ("Warning: do not use dbus_message_iter_init() on an unlocked message; lock it first with dbus_message_lock()\n");
+#endif
reader->gvariant = TRUE;
/* GVariant wraps contents into struct, but in this place type is already
* stripped off the parentheses (see get_const_signature()).