summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog27
-rw-r--r--dbus/dbus-marshal.c55
-rw-r--r--dbus/dbus-marshal.h1
-rw-r--r--dbus/dbus-message.c438
-rw-r--r--dbus/dbus-message.h1
-rw-r--r--doc/dbus-specification.sgml36
-rw-r--r--test/data/invalid-messages/array-with-mixed-types.message6
-rw-r--r--test/data/invalid-messages/too-short-dict.message3
-rw-r--r--test/data/valid-messages/array-of-array-of-uint32.message3
-rw-r--r--test/data/valid-messages/recursive-types.message79
10 files changed, 456 insertions, 193 deletions
diff --git a/ChangeLog b/ChangeLog
index 4222dc62..324f59c7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2003-04-10 Alexander Larsson <alexl@redhat.com>
+
+ * dbus/dbus-marshal.[ch]:
+ Add array_type_pos argument to _dbus_marshal_validate_arg.
+ Let you pass a NULL end_pos to _dbus_marshal_validate_type.
+
+ * dbus/dbus-message.[ch]:
+ Multi-dimensional arrays have full type specification in the
+ outermost array. Iter code re-arranged to handle this.
+ Added some more iter tests.
+
+ * doc/dbus-specification.sgml:
+ Add me to authors.
+ Remove old FIXME.
+ Update new array encoding description.
+ Correct DBUS_SERVICE_FLAGS_REPLACE_EXISTING description.
+
+ * test/data/invalid-messages/array-with-mixed-types.message:
+ * test/data/valid-messages/array-of-array-of-uint32.message:
+ Change to the new array format.
+
+ * test/data/invalid-messages/too-short-dict.message:
+ Fix bug in test.
+
+ * test/data/valid-messages/recursive-types.message:
+ Fix up and extend test.
+
2003-04-10 Havoc Pennington <hp@pobox.com>
* bus/dispatch.c: lots of fixes
diff --git a/dbus/dbus-marshal.c b/dbus/dbus-marshal.c
index b1eb6fc7..02343174 100644
--- a/dbus/dbus-marshal.c
+++ b/dbus/dbus-marshal.c
@@ -1027,8 +1027,8 @@ _dbus_marshal_get_arg_end_pos (const DBusString *str,
{
int len;
- /* Demarshal the length (element type is at pos + 0 */
- len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
+ /* Demarshal the length */
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
*end_pos = pos + len;
}
@@ -1169,7 +1169,8 @@ _dbus_marshal_validate_type (const DBusString *str,
if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
{
*type = *data;
- *end_pos = pos + 1;
+ if (end_pos != NULL)
+ *end_pos = pos + 1;
return TRUE;
}
@@ -1194,6 +1195,8 @@ _dbus_marshal_validate_type (const DBusString *str,
* @param byte_order the byte order to use
* @param depth current recursion depth, to prevent excessive recursion
* @param type the type of the argument
+ * @param array_type_pos the position of the current array type, or
+ * -1 if not in an array
* @param pos the pos where the arg starts
* @param end_pos pointer where the position right
* after the end position will follow
@@ -1204,6 +1207,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
int byte_order,
int depth,
int type,
+ int array_type_pos,
int pos,
int *end_pos)
{
@@ -1340,21 +1344,38 @@ _dbus_marshal_validate_arg (const DBusString *str,
int end;
int array_type;
- if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
+ if (array_type_pos == -1)
+ {
+ array_type_pos = pos;
+
+ do
+ {
+ if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
+ {
+ _dbus_verbose ("invalid array type\n");
+ return FALSE;
+ }
+
+ /* NIL values take up no space, so you couldn't iterate over an array of them.
+ * array of nil seems useless anyway; the useful thing might be array of
+ * (nil OR string) but we have no framework for that.
+ */
+ if (array_type == DBUS_TYPE_NIL)
+ {
+ _dbus_verbose ("array of NIL is not allowed\n");
+ return FALSE;
+ }
+ }
+ while (array_type == DBUS_TYPE_ARRAY);
+ }
+ else
+ array_type_pos++;
+
+ if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
{
_dbus_verbose ("invalid array type\n");
return FALSE;
}
-
- /* NIL values take up no space, so you couldn't iterate over an array of them.
- * array of nil seems useless anyway; the useful thing might be array of
- * (nil OR string) but we have no framework for that.
- */
- if (array_type == DBUS_TYPE_NIL)
- {
- _dbus_verbose ("array of NIL is not allowed\n");
- return FALSE;
- }
len = demarshal_and_validate_len (str, byte_order, pos, &pos);
if (len < 0)
@@ -1371,7 +1392,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
while (pos < end)
{
if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
- array_type, pos, &pos))
+ array_type, array_type_pos, pos, &pos))
return FALSE;
}
@@ -1417,7 +1438,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
{
/* Validate name */
if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
- DBUS_TYPE_STRING, pos, &pos))
+ DBUS_TYPE_STRING, -1, pos, &pos))
return FALSE;
if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
@@ -1428,7 +1449,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
/* Validate element */
if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
- dict_type, pos, &pos))
+ dict_type, -1, pos, &pos))
return FALSE;
}
diff --git a/dbus/dbus-marshal.h b/dbus/dbus-marshal.h
index 81ff6f50..53b9b7b3 100644
--- a/dbus/dbus-marshal.h
+++ b/dbus/dbus-marshal.h
@@ -186,6 +186,7 @@ dbus_bool_t _dbus_marshal_validate_arg (const DBusString *str,
int depth,
int byte_order,
int type,
+ int array_type_pos,
int pos,
int *end_pos);
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index 6bddc3f0..64cfb864 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -133,10 +133,13 @@ struct DBusMessageRealIter
int pos; /**< Current position in the string */
int end; /**< position right after the container */
- int container_type; /**< type of the items in the container (used for arrays) */
int container_start; /**< offset of the start of the container */
int container_length_pos; /**< offset of the length of the container */
+
int wrote_dict_key; /**< whether we wrote the dict key for the current dict element */
+
+ int array_type_pos; /**< pointer to the position of the array element type */
+ int array_type_done; /**< TRUE if the array type is fully finished */
};
/**
@@ -1571,10 +1574,10 @@ dbus_message_iter_init (DBusMessage *message,
real->pos = 0;
real->end = _dbus_string_get_length (&message->body);
- real->container_type = 0;
real->container_start = 0;
real->container_length_pos = 0;
real->wrote_dict_key = 0;
+ real->array_type_pos = 0;
}
static void
@@ -1587,6 +1590,21 @@ dbus_message_iter_check (DBusMessageRealIter *iter)
}
static int
+skip_array_type (DBusMessageRealIter *iter, int pos)
+{
+ const char *data;
+
+ do
+ {
+ data = _dbus_string_get_const_data_len (&iter->message->body,
+ pos++, 1);
+ }
+ while (*data == DBUS_TYPE_ARRAY);
+
+ return pos;
+}
+
+static int
dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
{
const char *data;
@@ -1602,12 +1620,17 @@ dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
else
*type = DBUS_TYPE_INVALID;
- return iter->pos + 1;
+ return skip_array_type (iter, iter->pos);
case DBUS_MESSAGE_ITER_TYPE_ARRAY:
- *type = iter->container_type;
- return iter->pos;
+ data = _dbus_string_get_const_data_len (&iter->message->body,
+ iter->array_type_pos, 1);
+ if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
+ *type = *data;
+ else
+ *type = DBUS_TYPE_INVALID;
+ return iter->pos;
case DBUS_MESSAGE_ITER_TYPE_DICT:
/* Get the length of the string */
@@ -1615,13 +1638,16 @@ dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
iter->message->byte_order,
iter->pos, &pos);
pos = pos + len + 1;
+
data = _dbus_string_get_const_data_len (&iter->message->body,
pos, 1);
if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
*type = *data;
else
*type = DBUS_TYPE_INVALID;
- return pos + 1;
+
+ return skip_array_type (iter, pos);
+
default:
_dbus_assert_not_reached ("Invalid iter type");
break;
@@ -1716,6 +1742,48 @@ dbus_message_iter_get_arg_type (DBusMessageIter *iter)
return type;
}
+static int
+iter_get_array_type (DBusMessageRealIter *iter, int *array_type_pos)
+{
+ const char *data;
+ int _array_type_pos;
+ int len, pos;
+
+ switch (iter->type)
+ {
+ case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
+ _array_type_pos = iter->pos + 1;
+ break;
+ case DBUS_MESSAGE_ITER_TYPE_ARRAY:
+ _array_type_pos = iter->array_type_pos + 1;
+ break;
+ case DBUS_MESSAGE_ITER_TYPE_DICT:
+ /* Get the length of the string */
+ len = _dbus_demarshal_uint32 (&iter->message->body,
+ iter->message->byte_order,
+ iter->pos, &pos);
+ pos = pos + len + 1;
+ data = _dbus_string_get_const_data_len (&iter->message->body,
+ pos + 1, 1);
+ _array_type_pos = pos + 1;
+ break;
+ default:
+ _dbus_assert_not_reached ("wrong iter type");
+ return DBUS_TYPE_INVALID;
+ }
+
+ if (array_type_pos != NULL)
+ *array_type_pos = _array_type_pos;
+
+ data = _dbus_string_get_const_data_len (&iter->message->body,
+ _array_type_pos, 1);
+ if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
+ return *data;
+
+ return DBUS_TYPE_INVALID;
+}
+
+
/**
* Returns the element type of the array that the
* message iterator points at. Note that you need
@@ -1730,7 +1798,6 @@ dbus_message_iter_get_array_type (DBusMessageIter *iter)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
int type, pos;
- const char *data;
dbus_message_iter_check (real);
@@ -1741,13 +1808,7 @@ dbus_message_iter_get_array_type (DBusMessageIter *iter)
_dbus_assert (type == DBUS_TYPE_ARRAY);
- data = _dbus_string_get_const_data_len (&real->message->body,
- pos,
- 1);
- if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
- return *data;
-
- return DBUS_TYPE_INVALID;
+ return iter_get_array_type (real, NULL);
}
@@ -1970,9 +2031,8 @@ dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
- int type, pos, len_pos, len;
+ int type, pos, len_pos, len, array_type_pos;
int _array_type;
- const char *data;
dbus_message_iter_check (real);
@@ -1980,17 +2040,11 @@ dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
_dbus_assert (type == DBUS_TYPE_ARRAY);
- data = _dbus_string_get_const_data_len (&real->message->body,
- pos,
- 1);
- if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
- _array_type = *data;
- else
- return FALSE;
-
- len_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t));
+ _array_type = iter_get_array_type (real, &array_type_pos);
+
+ len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
- pos + 1, &pos);
+ pos, &pos);
array_real->parent_iter = real;
array_real->message = real->message;
@@ -2000,11 +2054,12 @@ dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
array_real->pos = pos;
array_real->end = pos + len;
- array_real->container_type = _array_type;
array_real->container_start = pos;
array_real->container_length_pos = len_pos;
array_real->wrote_dict_key = 0;
-
+ array_real->array_type_pos = array_type_pos;
+ array_real->array_type_done = TRUE;
+
if (array_type != NULL)
*array_type = _array_type;
@@ -2047,7 +2102,6 @@ dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
dict_real->pos = pos;
dict_real->end = pos + len;
- dict_real->container_type = 0;
dict_real->container_start = pos;
dict_real->container_length_pos = len_pos;
dict_real->wrote_dict_key = 0;
@@ -2072,7 +2126,6 @@ dbus_message_iter_get_byte_array (DBusMessageIter *iter,
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
int type, pos;
- const char *data;
dbus_message_iter_check (real);
@@ -2080,14 +2133,12 @@ dbus_message_iter_get_byte_array (DBusMessageIter *iter,
_dbus_assert (type == DBUS_TYPE_ARRAY);
- data = _dbus_string_get_const_data_len (&real->message->body,
- pos,
- 1);
+ type = iter_get_array_type (real, NULL);
- _dbus_assert (*data == DBUS_TYPE_BYTE);
+ _dbus_assert (type == DBUS_TYPE_BYTE);
if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
- pos + 1, NULL, value, len))
+ pos, NULL, value, len))
return FALSE;
else
return TRUE;
@@ -2110,7 +2161,6 @@ dbus_message_iter_get_boolean_array (DBusMessageIter *iter,
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
int type, pos;
- const char *data;
dbus_message_iter_check (real);
@@ -2118,14 +2168,12 @@ dbus_message_iter_get_boolean_array (DBusMessageIter *iter,
_dbus_assert (type == DBUS_TYPE_ARRAY);
- data = _dbus_string_get_const_data_len (&real->message->body,
- pos,
- 1);
+ type = iter_get_array_type (real, NULL);
- _dbus_assert (*data == DBUS_TYPE_BOOLEAN);
+ _dbus_assert (type == DBUS_TYPE_BOOLEAN);
if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
- pos + 1, NULL, value, len))
+ pos, NULL, value, len))
return FALSE;
else
return TRUE;
@@ -2148,7 +2196,6 @@ dbus_message_iter_get_int32_array (DBusMessageIter *iter,
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
int type, pos;
- const char *data;
dbus_message_iter_check (real);
@@ -2156,14 +2203,12 @@ dbus_message_iter_get_int32_array (DBusMessageIter *iter,
_dbus_assert (type == DBUS_TYPE_ARRAY);
- data = _dbus_string_get_const_data_len (&real->message->body,
- pos,
- 1);
-
- _dbus_assert (*data == DBUS_TYPE_INT32);
+ type = iter_get_array_type (real, NULL);
+
+ _dbus_assert (type == DBUS_TYPE_INT32);
if (!_dbus_demarshal_int32_array (&real->message->body, real->message->byte_order,
- pos + 1, NULL, value, len))
+ pos, NULL, value, len))
return FALSE;
else
return TRUE;
@@ -2186,7 +2231,6 @@ dbus_message_iter_get_uint32_array (DBusMessageIter *iter,
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
int type, pos;
- const char *data;
dbus_message_iter_check (real);
@@ -2194,14 +2238,11 @@ dbus_message_iter_get_uint32_array (DBusMessageIter *iter,
_dbus_assert (type == DBUS_TYPE_ARRAY);
- data = _dbus_string_get_const_data_len (&real->message->body,
- pos,
- 1);
-
- _dbus_assert (*data == DBUS_TYPE_UINT32);
+ type = iter_get_array_type (real, NULL);
+ _dbus_assert (type == DBUS_TYPE_UINT32);
if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
- pos + 1, NULL, value, len))
+ pos, NULL, value, len))
return FALSE;
else
return TRUE;
@@ -2224,7 +2265,6 @@ dbus_message_iter_get_double_array (DBusMessageIter *iter,
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
int type, pos;
- const char *data;
dbus_message_iter_check (real);
@@ -2232,14 +2272,11 @@ dbus_message_iter_get_double_array (DBusMessageIter *iter,
_dbus_assert (type == DBUS_TYPE_ARRAY);
- data = _dbus_string_get_const_data_len (&real->message->body,
- pos,
- 1);
-
- _dbus_assert (*data == DBUS_TYPE_DOUBLE);
+ type = iter_get_array_type (real, NULL);
+ _dbus_assert (type == DBUS_TYPE_DOUBLE);
if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
- pos + 1, NULL, value, len))
+ pos, NULL, value, len))
return FALSE;
else
return TRUE;
@@ -2267,7 +2304,6 @@ dbus_message_iter_get_string_array (DBusMessageIter *iter,
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
int type, pos;
- const char *data;
dbus_message_iter_check (real);
@@ -2275,14 +2311,11 @@ dbus_message_iter_get_string_array (DBusMessageIter *iter,
_dbus_assert (type == DBUS_TYPE_ARRAY);
- data = _dbus_string_get_const_data_len (&real->message->body,
- pos,
- 1);
-
- _dbus_assert (*data == DBUS_TYPE_STRING);
+ type = iter_get_array_type (real, NULL);
+ _dbus_assert (type == DBUS_TYPE_STRING);
if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
- pos + 1, NULL, value, len))
+ pos, NULL, value, len))
return FALSE;
else
return TRUE;
@@ -2332,7 +2365,6 @@ dbus_message_append_iter_init (DBusMessage *message,
real->end = _dbus_string_get_length (&real->message->body);
real->pos = real->end;
- real->container_type = 0;
real->container_length_pos = 0;
real->wrote_dict_key = 0;
}
@@ -2356,6 +2388,7 @@ static dbus_bool_t
dbus_message_iter_append_type (DBusMessageRealIter *iter,
int type)
{
+ const char *data;
switch (iter->type)
{
case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
@@ -2364,7 +2397,9 @@ dbus_message_iter_append_type (DBusMessageRealIter *iter,
break;
case DBUS_MESSAGE_ITER_TYPE_ARRAY:
- if (type != iter->container_type)
+ data = _dbus_string_get_const_data_len (&iter->message->body,
+ iter->array_type_pos, 1);
+ if (type != *data)
{
_dbus_warn ("Appended element of wrong type for array\n");
return FALSE;
@@ -2402,7 +2437,7 @@ dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
/* Set container length */
if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
- iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
+ (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
_dbus_marshal_set_uint32 (&iter->message->body,
iter->message->byte_order,
iter->container_length_pos,
@@ -2689,6 +2724,81 @@ dbus_message_iter_append_dict_key (DBusMessageIter *iter,
return TRUE;
}
+static dbus_bool_t
+array_iter_type_mark_done (DBusMessageRealIter *iter)
+{
+ int len_pos;
+
+ if (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
+ array_iter_type_mark_done (iter->parent_iter);
+ else
+ return TRUE;
+
+ len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&iter->message->body),
+ sizeof (dbus_uint32_t));
+
+ /* Empty length for now, backfill later */
+ if (!_dbus_marshal_uint32 (&iter->message->body, iter->message->byte_order, 0))
+ {
+ _dbus_string_set_length (&iter->message->body, iter->pos);
+ return FALSE;
+ }
+
+ iter->container_start = _dbus_string_get_length (&iter->message->body);
+ iter->container_length_pos = len_pos;
+ iter->array_type_done = TRUE;
+
+ return TRUE;
+}
+
+static dbus_bool_t
+append_array_type (DBusMessageRealIter *real,
+ int element_type,
+ dbus_bool_t *array_type_done,
+ int *array_type_pos)
+{
+ int existing_element_type;
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ return FALSE;
+
+ if (real->type == DBUS_MESSAGE_ITER_TYPE_ARRAY &&
+ real->array_type_done)
+ {
+ existing_element_type = iter_get_array_type (real, array_type_pos);
+ if (existing_element_type != element_type)
+ {
+ _dbus_warn ("Appending array of %d, when expecting array of %d\n",
+ element_type, existing_element_type);
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+ if (array_type_done != NULL)
+ *array_type_done = TRUE;
+ }
+ else
+ {
+ if (array_type_pos != NULL)
+ *array_type_pos = _dbus_string_get_length (&real->message->body);
+
+ /* Append element type */
+ if (!_dbus_string_append_byte (&real->message->body, element_type))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ if (array_type_done != NULL)
+ *array_type_done = element_type != DBUS_TYPE_ARRAY;
+
+ if (element_type != DBUS_TYPE_ARRAY &&
+ !array_iter_type_mark_done (real))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/**
* Appends an array to the message and initializes an iterator that
* can be used to append to the array.
@@ -2706,25 +2816,30 @@ dbus_message_iter_append_array (DBusMessageIter *iter,
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
int len_pos;
+ int array_type_pos;
+ dbus_bool_t array_type_done;
- dbus_message_iter_append_check (real);
-
- if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
- return FALSE;
-
- if (!_dbus_string_append_byte (&real->message->body, element_type))
+ if (element_type == DBUS_TYPE_NIL)
{
- _dbus_string_set_length (&real->message->body, real->pos);
+ _dbus_warn ("Can't create NIL arrays\n");
return FALSE;
}
+
+ dbus_message_iter_append_check (real);
+
+ if (!append_array_type (real, element_type, &array_type_done, &array_type_pos))
+ return FALSE;
len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
- /* Empty length for now, backfill later */
- if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
+ if (array_type_done)
{
- _dbus_string_set_length (&real->message->body, real->pos);
- return FALSE;
+ /* Empty length for now, backfill later */
+ if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
}
array_real->parent_iter = real;
@@ -2735,10 +2850,11 @@ dbus_message_iter_append_array (DBusMessageIter *iter,
array_real->pos = _dbus_string_get_length (&real->message->body);
array_real->end = array_real->end;
- array_real->container_type = element_type;
array_real->container_start = array_real->pos;
array_real->container_length_pos = len_pos;
array_real->wrote_dict_key = 0;
+ array_real->array_type_done = array_type_done;
+ array_real->array_type_pos = array_type_pos;
dbus_message_iter_append_done (array_real);
@@ -2784,7 +2900,6 @@ dbus_message_iter_append_dict (DBusMessageIter *iter,
dict_real->pos = _dbus_string_get_length (&real->message->body);
dict_real->end = dict_real->end;
- dict_real->container_type = 0;
dict_real->container_start = dict_real->pos;
dict_real->container_length_pos = len_pos;
dict_real->wrote_dict_key = 0;
@@ -2812,15 +2927,9 @@ dbus_message_iter_append_boolean_array (DBusMessageIter *iter,
dbus_message_iter_append_check (real);
- if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ if (!append_array_type (real, DBUS_TYPE_BOOLEAN, NULL, NULL))
return FALSE;
- if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BOOLEAN))
- {
- _dbus_string_set_length (&real->message->body, real->pos);
- return FALSE;
- }
-
if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
{
_dbus_string_set_length (&real->message->body, real->pos);
@@ -2849,15 +2958,9 @@ dbus_message_iter_append_int32_array (DBusMessageIter *iter,
dbus_message_iter_append_check (real);
- if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ if (!append_array_type (real, DBUS_TYPE_INT32, NULL, NULL))
return FALSE;
- if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_INT32))
- {
- _dbus_string_set_length (&real->message->body, real->pos);
- return FALSE;
- }
-
if (!_dbus_marshal_int32_array (&real->message->body, real->message->byte_order, value, len))
{
_dbus_string_set_length (&real->message->body, real->pos);
@@ -2886,15 +2989,9 @@ dbus_message_iter_append_uint32_array (DBusMessageIter *iter,
dbus_message_iter_append_check (real);
- if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ if (!append_array_type (real, DBUS_TYPE_UINT32, NULL, NULL))
return FALSE;
- if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_UINT32))
- {
- _dbus_string_set_length (&real->message->body, real->pos);
- return FALSE;
- }
-
if (!_dbus_marshal_uint32_array (&real->message->body, real->message->byte_order, value, len))
{
_dbus_string_set_length (&real->message->body, real->pos);
@@ -2923,15 +3020,9 @@ dbus_message_iter_append_double_array (DBusMessageIter *iter,
dbus_message_iter_append_check (real);
- if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ if (!append_array_type (real, DBUS_TYPE_DOUBLE, NULL, NULL))
return FALSE;
- if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_DOUBLE))
- {
- _dbus_string_set_length (&real->message->body, real->pos);
- return FALSE;
- }
-
if (!_dbus_marshal_double_array (&real->message->body, real->message->byte_order, value, len))
{
_dbus_string_set_length (&real->message->body, real->pos);
@@ -2960,15 +3051,9 @@ dbus_message_iter_append_byte_array (DBusMessageIter *iter,
dbus_message_iter_append_check (real);
- if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ if (!append_array_type (real, DBUS_TYPE_BYTE, NULL, NULL))
return FALSE;
- if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BYTE))
- {
- _dbus_string_set_length (&real->message->body, real->pos);
- return FALSE;
- }
-
if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
{
_dbus_string_set_length (&real->message->body, real->pos);
@@ -2997,15 +3082,9 @@ dbus_message_iter_append_string_array (DBusMessageIter *iter,
dbus_message_iter_append_check (real);
- if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
return FALSE;
- if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BYTE))
- {
- _dbus_string_set_length (&real->message->body, real->pos);
- return FALSE;
- }
-
if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
{
_dbus_string_set_length (&real->message->body, real->pos);
@@ -3524,7 +3603,7 @@ decode_header_data (const DBusString *data,
return FALSE;
}
- if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, pos, &new_pos))
+ if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
{
_dbus_verbose ("Failed to validate argument to named header field\n");
return FALSE;
@@ -3706,7 +3785,7 @@ _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
if (!_dbus_marshal_validate_arg (&loader->data,
byte_order,
0,
- type,
+ type, -1,
next_arg,
&next_arg))
{
@@ -3898,8 +3977,10 @@ _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader)
static void
message_iter_test (DBusMessage *message)
{
- DBusMessageIter iter, dict, array;
+ DBusMessageIter iter, dict, array, array2;
char *str;
+ dbus_int32_t *our_int_array;
+ int array_len;
dbus_message_iter_init (message, &iter);
@@ -3976,6 +4057,9 @@ message_iter_test (DBusMessage *message)
if (!dbus_message_iter_next (&iter))
_dbus_assert_not_reached ("Reached end of arguments");
+
+ /* dict */
+
if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
_dbus_assert_not_reached ("not dict type");
@@ -3993,6 +4077,69 @@ message_iter_test (DBusMessage *message)
if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
_dbus_assert_not_reached ("wrong dict entry value");
+ if (!dbus_message_iter_next (&dict))
+ _dbus_assert_not_reached ("reached end of dict");
+
+ /* array of array of int32 (in dict) */
+
+ str = dbus_message_iter_get_dict_key (&dict);
+ if (str == NULL || strcmp (str, "array") != 0)
+ _dbus_assert_not_reached ("wrong dict key");
+ dbus_free (str);
+
+ if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_ARRAY)
+ _dbus_assert_not_reached ("Argument type not an array");
+
+ if (dbus_message_iter_get_array_type (&dict) != DBUS_TYPE_ARRAY)
+ _dbus_assert_not_reached ("Array type not array");
+
+ if (!dbus_message_iter_init_array_iterator (&dict, &array, NULL))
+ _dbus_assert_not_reached ("Array init failed");
+
+ if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_ARRAY)
+ _dbus_assert_not_reached ("Argument type isn't array");
+
+ if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
+ _dbus_assert_not_reached ("Array type not int32");
+
+ if (!dbus_message_iter_init_array_iterator (&array, &array2, NULL))
+ _dbus_assert_not_reached ("Array init failed");
+
+ if (dbus_message_iter_get_arg_type (&array2) != DBUS_TYPE_INT32)
+ _dbus_assert_not_reached ("Argument type isn't int32");
+
+ if (dbus_message_iter_get_int32 (&array2) != 0x12345678)
+ _dbus_assert_not_reached ("Signed integers differ");
+
+ if (!dbus_message_iter_next (&array2))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_int32 (&array2) != 0x23456781)
+ _dbus_assert_not_reached ("Signed integers differ");
+
+ if (dbus_message_iter_next (&array2))
+ _dbus_assert_not_reached ("Didn't reached end of arguments");
+
+ if (!dbus_message_iter_next (&array))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
+ _dbus_assert_not_reached ("Array type not int32");
+
+ if (!dbus_message_iter_get_int32_array (&array,
+ &our_int_array,
+ &array_len))
+ _dbus_assert_not_reached ("couldn't get int32 array");
+
+ _dbus_assert (array_len == 3);
+ _dbus_assert (our_int_array[0] == 0x34567812 &&
+ our_int_array[1] == 0x45678123 &&
+ our_int_array[2] == 0x56781234);
+ dbus_free (our_int_array);
+
+ if (dbus_message_iter_next (&array))
+ _dbus_assert_not_reached ("Didn't reach end of array");
+
if (dbus_message_iter_next (&dict))
_dbus_assert_not_reached ("Didn't reach end of dict");
@@ -4005,6 +4152,7 @@ message_iter_test (DBusMessage *message)
if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
_dbus_assert_not_reached ("wrong value after dict");
+
if (dbus_message_iter_next (&iter))
_dbus_assert_not_reached ("Didn't reach end of arguments");
}
@@ -4106,7 +4254,7 @@ check_message_handling_type (DBusMessageIter *iter,
return FALSE;
}
dbus_free (key);
-
+
if (!check_message_handling_type (&child_iter, entry_type))
{
_dbus_warn ("error in dict value\n");
@@ -4157,7 +4305,6 @@ check_message_handling (DBusMessage *message)
dbus_message_iter_init (message, &iter);
while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
{
-
if (!check_message_handling_type (&iter, type))
goto failed;
@@ -4645,6 +4792,7 @@ verify_test_message (DBusMessage *message)
double our_double;
dbus_bool_t our_bool;
dbus_int32_t *our_int_array;
+ dbus_uint32_t our_uint32;
int our_int_array_len;
DBusMessageIter iter, dict;
DBusError error;
@@ -4705,8 +4853,11 @@ verify_test_message (DBusMessage *message)
_dbus_assert_not_reached ("wrong dict entry type");
}
- if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
- _dbus_assert_not_reached ("wrong dict entry value");
+ if ((our_uint32 = dbus_message_iter_get_uint32 (&dict)) != 0xDEADBEEF)
+ {
+ _dbus_verbose ("dict entry val: %x\n", our_uint32);
+ _dbus_assert_not_reached ("wrong dict entry value");
+ }
if (dbus_message_iter_next (&dict))
_dbus_assert_not_reached ("Didn't reach end of dict");
@@ -4735,7 +4886,7 @@ _dbus_message_test (const char *test_data_dir)
{
DBusMessage *message;
DBusMessageLoader *loader;
- DBusMessageIter iter, child_iter;
+ DBusMessageIter iter, child_iter, child_iter2, child_iter3;
int i;
const char *data;
DBusMessage *copy;
@@ -4805,10 +4956,27 @@ _dbus_message_test (const char *test_data_dir)
dbus_message_iter_append_uint32 (&child_iter, 0x12345678);
dbus_message_iter_append_uint32 (&child_iter, 0x23456781);
+ /* dict */
dbus_message_iter_append_dict (&iter, &child_iter);
dbus_message_iter_append_dict_key (&child_iter, "test");
dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
+
+ /* array of array of int32 (in dict) */
+ dbus_message_iter_append_dict_key (&child_iter, "array");
+ dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
+ dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
+ dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
+ dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
+ _dbus_warn ("next call expected to fail with wrong array type\n");
+ _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
+ dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
+ dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
+ dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
+ dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
+
dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
+
+
message_iter_test (message);
diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h
index 6a940536..809dc3ed 100644
--- a/dbus/dbus-message.h
+++ b/dbus/dbus-message.h
@@ -48,6 +48,7 @@ struct DBusMessageIter
int dummy8;
int dummy9;
int dummy10;
+ int dummy11;
int pad1;
int pad2;
void *pad3;
diff --git a/doc/dbus-specification.sgml b/doc/dbus-specification.sgml
index 5a7a80fa..0bbc3cda 100644
--- a/doc/dbus-specification.sgml
+++ b/doc/dbus-specification.sgml
@@ -10,6 +10,7 @@
<firstname>Havoc</firstname>
<surname>Pennington</surname>
<affiliation>
+ <orgname>Red Hat, Inc</orgname>
<address>
<email>hp@pobox.com</email>
</address>
@@ -25,6 +26,16 @@
</address>
</affiliation>
</author>
+ <author>
+ <firstname>Alexander</firstname>
+ <surname>Larsson</surname>
+ <affiliation>
+ <orgname>Red Hat, Inc</orgname>
+ <address>
+ <email>alexl@redhat.com</email>
+ </address>
+ </affiliation>
+ </author>
</authorgroup>
</artheader>
@@ -283,9 +294,6 @@
in a type-dependent format.
</para>
<para>
- [FIXME perhaps we should add type BYTE with the primary
- advantage being that it occupies 1 byte vs. 7 for UINT32,
- or perhaps space savings aren't worth the complexity]
<informaltable>
<tgroup cols=3>
<thead>
@@ -307,7 +315,7 @@
</row><row>
<entry>BYTE</entry>
<entry>2</entry>
- <entry>8-bit unsigned integer.</entry>
+ <entry>8-bit unsigned integer</entry>
</row><row>
<entry>BOOLEAN</entry>
<entry>3</entry>
@@ -365,10 +373,10 @@
by the type code of the next argument.</entry>
</row><row>
<entry>BYTE</entry>
- <entry>a byte.</entry>
+ <entry>A byte.</entry>
</row><row>
<entry>BOOLEAN</entry>
- <entry>a byte, with valid values 0 and 1.</entry>
+ <entry>A byte, with valid values 0 and 1.</entry>
</row><row>
<entry>INT32</entry>
<entry>32-bit signed integer in the message's byte order, aligned to 4-byte boundary.</entry>
@@ -393,11 +401,13 @@
</entry>
</row><row>
<entry>ARRAY</entry>
- <entry>a byte giving the element type of the array followed
- by an UINT32 (aligned to 4 bytes) giving the length of the
- array data in bytes. This is then followed by a number of
- entries with the same type, encoded like that type normally
- would be encoded alone.
+ <entry>A sequence of bytes giving the element type of the array, terminated
+ by a type different from ARRAY (just one byte for one-dimensional arrays, but
+ larger for multi-dimensional arrays), followed by an UINT32 (aligned to 4 bytes)
+ giving the length of the array data in bytes. This is followed by each array entry
+ encoded the way it would normally be encoded, except arrays, which are encoded
+ without the type information, since that is already declared above. Arrays containing
+ NIL are not allowed.
</entry>
</row><row>
<entry>DICT</entry>
@@ -1524,7 +1534,9 @@
<row>
<entry>DBUS_SERVICE_FLAGS_REPLACE_EXISTING</entry>
<entry>0x2</entry>
- <entry>Only become the owner of the service if there is no current owner.</entry>
+ <entry>Try to replace the current owner if there is one. If this flag
+ is not set the application will only become the owner of the service if
+ there is no current owner.</entry>
</row>
</tbody>
</tgroup>
diff --git a/test/data/invalid-messages/array-with-mixed-types.message b/test/data/invalid-messages/array-with-mixed-types.message
index a7ff1e69..763a6c29 100644
--- a/test/data/invalid-messages/array-with-mixed-types.message
+++ b/test/data/invalid-messages/array-with-mixed-types.message
@@ -11,12 +11,12 @@ START_LENGTH Body
TYPE ARRAY
TYPE ARRAY
+TYPE UINT32
LENGTH Array
START_LENGTH Array
## array of uint32
-TYPE UINT32
LENGTH SubArray1
START_LENGTH SubArray1
UINT32 1
@@ -25,7 +25,6 @@ UINT32 3
END_LENGTH SubArray1
## array of uint32
-TYPE UINT32
LENGTH SubArray2
START_LENGTH SubArray2
UINT32 4
@@ -33,13 +32,10 @@ UINT32 5
END_LENGTH SubArray2
## array of boolean
-TYPE BOOLEAN
LENGTH SubArray3
START_LENGTH SubArray3
BOOLEAN false
BOOLEAN true
-BOOLEAN false
-BOOLEAN true
END_LENGTH SubArray3
END_LENGTH Array
diff --git a/test/data/invalid-messages/too-short-dict.message b/test/data/invalid-messages/too-short-dict.message
index 14722023..ba200461 100644
--- a/test/data/invalid-messages/too-short-dict.message
+++ b/test/data/invalid-messages/too-short-dict.message
@@ -8,8 +8,11 @@ END_LENGTH Header
ALIGN 8
START_LENGTH Body
TYPE DICT
+LENGTH Dict
+START_LENGTH Dict
STRING 'uint32'
TYPE UINT32
UINT32 0x8765432
STRING 'uint32'
+END_LENGTH Dict
END_LENGTH Body
diff --git a/test/data/valid-messages/array-of-array-of-uint32.message b/test/data/valid-messages/array-of-array-of-uint32.message
index 6baf4c36..82b8273d 100644
--- a/test/data/valid-messages/array-of-array-of-uint32.message
+++ b/test/data/valid-messages/array-of-array-of-uint32.message
@@ -10,12 +10,12 @@ START_LENGTH Body
TYPE ARRAY
TYPE ARRAY
+TYPE UINT32
LENGTH Array
START_LENGTH Array
## array of uint32
-TYPE UINT32
LENGTH SubArray1
START_LENGTH SubArray1
UINT32 1
@@ -24,7 +24,6 @@ UINT32 3
END_LENGTH SubArray1
## array of uint32
-TYPE UINT32
LENGTH SubArray2
START_LENGTH SubArray2
UINT32 4
diff --git a/test/data/valid-messages/recursive-types.message b/test/data/valid-messages/recursive-types.message
index b7608041..2ac6ad13 100644
--- a/test/data/valid-messages/recursive-types.message
+++ b/test/data/valid-messages/recursive-types.message
@@ -10,56 +10,91 @@ STRING 'org.freedesktop.Foo'
END_LENGTH Header
START_LENGTH Body
+# Everything is inside a dict
+TYPE DICT
+LENGTH Dict1
+START_LENGTH Dict1
+
+# first dict entry is an array of array of uint32
+STRING 'mega-uint-array'
+TYPE ARRAY
TYPE ARRAY
TYPE ARRAY
+TYPE UINT32
LENGTH Array1
START_LENGTH Array1
-
-TYPE UINT32
+LENGTH Array1_1
+START_LENGTH Array1_1
UINT32_ARRAY { 1, 2, 3, 4, 5}
+UINT32_ARRAY { 2, 3, 4, 5, 1}
+UINT32_ARRAY { 3, 4, 5, 1, 2}
+END_LENGTH Array1_1
+LENGTH Array1_2
+START_LENGTH Array1_2
+UINT32_ARRAY { 4, 5, 6, 7, 8}
+UINT32_ARRAY { 5, 6, 7, 8, 4}
+END_LENGTH Array1_2
+
+END_LENGTH Array1
+# second dict entry is an array of strings
+STRING 'string-array'
+TYPE ARRAY
TYPE STRING
STRING_ARRAY { 'a', 'string', 'array'}
-
+# third dict entry is another dict
+STRING 'nested-dict'
TYPE DICT
-LENGTH Array2
-START_LENGTH Array2
-
-LENGTH Dict1
-START_LENGTH Dict1
-STRING 'uint32'
-TYPE UINT32
-UINT32 1234
-STRING uint32'
-TYPE INT32
-INT32 1234
-END_LENGTH Dict1
-
LENGTH Dict2
START_LENGTH Dict2
-STRING 'dict'
+STRING 'string'
+TYPE STRING
+STRING 'a deeply nested string'
+
+STRING 'super-nested-dict'
TYPE DICT
LENGTH Dict3
START_LENGTH Dict3
+
STRING 'double-array'
TYPE ARRAY
TYPE DOUBLE
DOUBLE_ARRAY {1.0, 2.0, 3.0}
+
+STRING 'dict-array'
+TYPE ARRAY
+TYPE DICT
+LENGTH Array2
+START_LENGTH Array2
+
+LENGTH Dict4
+START_LENGTH Dict4
+STRING 'key4'
+TYPE BYTE
+BYTE '4'
+END_LENGTH Dict4
+
+LENGTH Dict5
+START_LENGTH Dict5
+STRING 'key5'
+TYPE BYTE
+BYTE '5'
+END_LENGTH Dict5
+
+END_LENGTH Array2
+
STRING 'boolean'
TYPE BOOLEAN
BOOLEAN false
+
END_LENGTH Dict3
END_LENGTH Dict2
-END_LENGTH Array2
-
-
-END_LENGTH Array1
-
+END_LENGTH Dict1
END_LENGTH Body