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_warn ("Appending array of %s, when expecting array of %s\n",
+ _dbus_type_to_string (element_type),
+ _dbus_type_to_string (existing_element_type));
_dbus_string_set_length (&real->message->body, real->pos);
return FALSE;
}
#define DBUS_HEADER_FIELD_SENDER_AS_UINT32 \
FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
-/* FIXME impose max length on name, srvc, sndr */
+static dbus_bool_t
+decode_string_field (const DBusString *data,
+ HeaderField fields[FIELD_LAST],
+ int pos,
+ int type,
+ int field,
+ const char *field_name)
+{
+ DBusString tmp;
+ int string_data_pos;
+
+ if (fields[field].offset >= 0)
+ {
+ _dbus_verbose ("%s field provided twice\n",
+ field_name);
+ return FALSE;
+ }
+
+ if (type != DBUS_TYPE_STRING)
+ {
+ _dbus_verbose ("%s field has wrong type\n", field_name);
+ return FALSE;
+ }
+
+ /* skip padding after typecode, skip string length;
+ * we assume that the string arg has already been validated
+ * for sanity and UTF-8
+ */
+ string_data_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
+ _dbus_assert (string_data_pos < _dbus_string_get_length (data));
+
+ _dbus_string_init_const (&tmp,
+ _dbus_string_get_const_data (data) + string_data_pos);
+
+ if (field == FIELD_NAME)
+ {
+ if (!_dbus_string_validate_name (&tmp, 0, _dbus_string_get_length (&tmp)))
+ {
+ _dbus_verbose ("%s field has invalid content \"%s\"\n",
+ field_name, _dbus_string_get_const_data (&tmp));
+ return FALSE;
+ }
+
+ if (_dbus_string_starts_with_c_str (&tmp,
+ DBUS_NAMESPACE_LOCAL_MESSAGE))
+ {
+ _dbus_verbose ("Message is in the local namespace\n");
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!_dbus_string_validate_service (&tmp, 0, _dbus_string_get_length (&tmp)))
+ {
+ _dbus_verbose ("%s field has invalid content \"%s\"\n",
+ field_name, _dbus_string_get_const_data (&tmp));
+ return FALSE;
+ }
+ }
+
+ fields[field].offset = _DBUS_ALIGN_VALUE (pos, 4);
+
+#if 0
+ _dbus_verbose ("Found field %s name at offset %d\n",
+ field_name, fields[field].offset);
+#endif
+
+ return TRUE;
+}
+
static dbus_bool_t
decode_header_data (const DBusString *data,
int header_len,
pos += 4;
_dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
+
+ if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
+ {
+ _dbus_verbose ("Failed to validate type of named header field\n");
+ return FALSE;
+ }
+
+ 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;
+ }
+ if (new_pos > header_len)
+ {
+ _dbus_verbose ("Named header field tries to extend beyond header length\n");
+ return FALSE;
+ }
+
switch (DBUS_UINT32_FROM_BE (*(int*)field))
{
case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
- if (fields[FIELD_SERVICE].offset >= 0)
- {
- _dbus_verbose ("%s field provided twice\n",
- DBUS_HEADER_FIELD_SERVICE);
- return FALSE;
- }
-
- fields[FIELD_SERVICE].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
-#if 0
- _dbus_verbose ("Found service name at offset %d\n",
- fields[FIELD_SERVICE].offset);
-#endif
+ if (!decode_string_field (data, fields, pos, type,
+ FIELD_SERVICE,
+ DBUS_HEADER_FIELD_SERVICE))
+ return FALSE;
break;
case DBUS_HEADER_FIELD_NAME_AS_UINT32:
- if (fields[FIELD_NAME].offset >= 0)
- {
- _dbus_verbose ("%s field provided twice\n",
- DBUS_HEADER_FIELD_NAME);
- return FALSE;
- }
-
- fields[FIELD_NAME].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
-
-#if 0
- _dbus_verbose ("Found message name at offset %d\n",
- fields[FIELD_NAME].offset);
-#endif
+ if (!decode_string_field (data, fields, pos, type,
+ FIELD_NAME,
+ DBUS_HEADER_FIELD_NAME))
+ return FALSE;
break;
- case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
- if (fields[FIELD_SENDER].offset >= 0)
- {
- _dbus_verbose ("%s field provided twice\n",
- DBUS_HEADER_FIELD_SENDER);
- return FALSE;
- }
-
- fields[FIELD_SENDER].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
- _dbus_verbose ("Found sender name at offset %d\n",
- fields[FIELD_NAME].offset);
+ case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
+ if (!decode_string_field (data, fields, pos, type,
+ FIELD_SENDER,
+ DBUS_HEADER_FIELD_SENDER))
+ return FALSE;
break;
case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
DBUS_HEADER_FIELD_REPLY);
return FALSE;
}
+
+ if (type != DBUS_TYPE_UINT32)
+ {
+ _dbus_verbose ("%s field has wrong type\n", DBUS_HEADER_FIELD_REPLY);
+ return FALSE;
+ }
- fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
+ fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos, 4);
_dbus_verbose ("Found reply serial at offset %d\n",
fields[FIELD_REPLY_SERIAL].offset);
_dbus_verbose ("Ignoring an unknown header field: %c%c%c%c at offset %d\n",
field[0], field[1], field[2], field[3], pos);
}
-
- if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
- {
- _dbus_verbose ("Failed to validate type of named header field\n");
- return FALSE;
- }
-
- 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;
- }
-
- if (new_pos > header_len)
- {
- _dbus_verbose ("Named header field tries to extend beyond header length\n");
- return FALSE;
- }
pos = new_pos;
}
}
}
- if (fields[FIELD_NAME].offset < 0)
- {
- _dbus_verbose ("No %s field provided\n",
- DBUS_HEADER_FIELD_NAME);
- return FALSE;
- }
+ /* Name field is mandatory */
+ if (fields[FIELD_NAME].offset < 0)
+ {
+ _dbus_verbose ("No %s field provided\n",
+ DBUS_HEADER_FIELD_NAME);
+ return FALSE;
+ }
if (message_padding)
*message_padding = header_len - pos;
_dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
/* Test the vararg functions */
- message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
+ message = dbus_message_new ("org.freedesktop.DBus.Test", "test.Message");
_dbus_message_set_serial (message, 1);
dbus_message_append_args (message,
DBUS_TYPE_INT32, -0x12345678,
dbus_message_unref (message);
dbus_message_unref (copy);
- message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
+ message = dbus_message_new ("org.freedesktop.DBus.Test", "test.Message");
_dbus_message_set_serial (message, 1);
dbus_message_set_reply_serial (message, 0x12345678);
#include "dbus-marshal.h"
#define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
#include "dbus-string-private.h"
+#include "dbus-protocol.h"
/**
* @defgroup DBusString string class
return TRUE;
}
+/**
+ * Checks that the given range of the string is a valid message name
+ * in the D-BUS protocol. This includes a length restriction, etc.,
+ * see the specification. It does not validate UTF-8, that has to be
+ * done separately for now.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that isn't in the string.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_string_validate_name (const DBusString *str,
+ int start,
+ int len)
+{
+ const unsigned char *s;
+ const unsigned char *end;
+ dbus_bool_t saw_dot;
+
+ DBUS_CONST_STRING_PREAMBLE (str);
+ _dbus_assert (start >= 0);
+ _dbus_assert (len >= 0);
+ _dbus_assert (start <= real->len);
+
+ if (len > real->len - start)
+ return FALSE;
+
+ if (len > DBUS_MAXIMUM_NAME_LENGTH)
+ return FALSE;
+
+ if (len == 0)
+ return FALSE;
+
+ saw_dot = FALSE;
+ s = real->str + start;
+ end = s + len;
+ while (s != end)
+ {
+ if (*s == '.')
+ {
+ saw_dot = TRUE;
+ break;
+ }
+
+ ++s;
+ }
+
+ if (!saw_dot)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/**
+ * Checks that the given range of the string is a valid service name
+ * in the D-BUS protocol. This includes a length restriction, etc.,
+ * see the specification. It does not validate UTF-8, that has to be
+ * done separately for now.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that isn't in the string.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_string_validate_service (const DBusString *str,
+ int start,
+ int len)
+{
+ const unsigned char *s;
+ const unsigned char *end;
+ dbus_bool_t saw_dot;
+ dbus_bool_t is_base_service;
+
+ DBUS_CONST_STRING_PREAMBLE (str);
+ _dbus_assert (start >= 0);
+ _dbus_assert (len >= 0);
+ _dbus_assert (start <= real->len);
+
+ if (len > real->len - start)
+ return FALSE;
+
+ if (len > DBUS_MAXIMUM_NAME_LENGTH)
+ return FALSE;
+
+ if (len == 0)
+ return FALSE;
+
+ is_base_service = _dbus_string_get_byte (str, start) == ':';
+ if (is_base_service)
+ return TRUE; /* can have any content */
+
+ /* non-base-service must have the '.' indicating a namespace */
+
+ saw_dot = FALSE;
+ s = real->str + start;
+ end = s + len;
+ while (s != end)
+ {
+ if (*s == '.')
+ {
+ saw_dot = TRUE;
+ break;
+ }
+
+ ++s;
+ }
+
+ return saw_dot;
+}
+
/**
* Clears all allocated bytes in the string to zero.
*