summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS14
-rw-r--r--bus/driver.c184
-rw-r--r--configure.ac46
-rw-r--r--dbus/dbus-connection.c9
-rw-r--r--dbus/dbus-marshal-basic.c38
-rw-r--r--dbus/dbus-marshal-basic.h1
-rw-r--r--dbus/dbus-marshal-validate.c4
-rw-r--r--dbus/dbus-message-factory.c3
-rw-r--r--dbus/dbus-object-tree.c8
-rw-r--r--dbus/dbus-object-tree.h3
-rw-r--r--dbus/dbus-signature.c53
-rw-r--r--dbus/dbus-signature.h3
-rw-r--r--dbus/dbus-string-util.c88
-rw-r--r--dbus/dbus-string.c43
-rw-r--r--test/break-loader.c2
15 files changed, 326 insertions, 173 deletions
diff --git a/NEWS b/NEWS
index 2532e315..0ba97624 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,17 @@
+D-Bus 1.5.0 (UNRELEASED)
+==
+
+ • Let the bus daemon implement more than one interface (fd.o #33757,
+ Simon McVittie)
+ • Optimize _dbus_string_replace_len to reduce waste (fd.o #21261,
+ Roberto Guido)
+ • Require user intervention to compile with missing 64-bit support
+ (fd.o #35114, Simon McVittie)
+ • Add dbus_type_is_valid as public API (fd.o #20496, Simon McVittie)
+ • Raise UnknownObject instead of UnknownMethod for calls to methods on
+ paths that are not part of the object tree, and UnknownInterface for calls
+ to unknown interfaces in the bus daemon (fd.o #34527, Lennart Poettering)
+
D-Bus 1.4.8 (UNRELEASED)
==
diff --git a/bus/driver.c b/bus/driver.c
index cc8d1f26..425a3d5a 100644
--- a/bus/driver.c
+++ b/bus/driver.c
@@ -1644,11 +1644,7 @@ bus_driver_handle_get_id (DBusConnection *connection,
return FALSE;
}
-/* For speed it might be useful to sort this in order of
- * frequency of use (but doesn't matter with only a few items
- * anyhow)
- */
-static struct
+typedef struct
{
const char *name;
const char *in_args;
@@ -1657,7 +1653,13 @@ static struct
BusTransaction *transaction,
DBusMessage *message,
DBusError *error);
-} message_handlers[] = {
+} MessageHandler;
+
+/* For speed it might be useful to sort this in order of
+ * frequency of use (but doesn't matter with only a few items
+ * anyhow)
+ */
+static const MessageHandler dbus_message_handlers[] = {
{ "Hello",
"",
DBUS_TYPE_STRING_AS_STRING,
@@ -1729,7 +1731,41 @@ static struct
{ "GetId",
"",
DBUS_TYPE_STRING_AS_STRING,
- bus_driver_handle_get_id }
+ bus_driver_handle_get_id },
+ { NULL, NULL, NULL, NULL }
+};
+
+static dbus_bool_t bus_driver_handle_introspect (DBusConnection *,
+ BusTransaction *, DBusMessage *, DBusError *);
+
+static const MessageHandler introspectable_message_handlers[] = {
+ { "Introspect", "", DBUS_TYPE_STRING_AS_STRING, bus_driver_handle_introspect },
+ { NULL, NULL, NULL, NULL }
+};
+
+typedef struct {
+ const char *name;
+ const MessageHandler *message_handlers;
+ const char *extra_introspection;
+} InterfaceHandler;
+
+/* These should ideally be sorted by frequency of use, although it
+ * probably doesn't matter with this few items */
+static InterfaceHandler interface_handlers[] = {
+ { DBUS_INTERFACE_DBUS, dbus_message_handlers,
+ " <signal name=\"NameOwnerChanged\">\n"
+ " <arg type=\"s\"/>\n"
+ " <arg type=\"s\"/>\n"
+ " <arg type=\"s\"/>\n"
+ " </signal>\n"
+ " <signal name=\"NameLost\">\n"
+ " <arg type=\"s\"/>\n"
+ " </signal>\n"
+ " <signal name=\"NameAcquired\">\n"
+ " <arg type=\"s\"/>\n"
+ " </signal>\n" },
+ { DBUS_INTERFACE_INTROSPECTABLE, introspectable_message_handlers, NULL },
+ { NULL, NULL, NULL }
};
static dbus_bool_t
@@ -1770,86 +1806,43 @@ write_args_for_direction (DBusString *xml,
dbus_bool_t
bus_driver_generate_introspect_string (DBusString *xml)
{
- int i;
+ const InterfaceHandler *ih;
+ const MessageHandler *mh;
if (!_dbus_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
return FALSE;
if (!_dbus_string_append (xml, "<node>\n"))
return FALSE;
- if (!_dbus_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE))
- return FALSE;
- if (!_dbus_string_append (xml, " <method name=\"Introspect\">\n"))
- return FALSE;
- if (!_dbus_string_append_printf (xml, " <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING))
- return FALSE;
- if (!_dbus_string_append (xml, " </method>\n"))
- return FALSE;
- if (!_dbus_string_append (xml, " </interface>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <interface name=\"%s\">\n",
- DBUS_INTERFACE_DBUS))
- return FALSE;
- i = 0;
- while (i < _DBUS_N_ELEMENTS (message_handlers))
+ for (ih = interface_handlers; ih->name != NULL; ih++)
{
-
- if (!_dbus_string_append_printf (xml, " <method name=\"%s\">\n",
- message_handlers[i].name))
+ if (!_dbus_string_append_printf (xml, " <interface name=\"%s\">\n",
+ ih->name))
return FALSE;
- if (!write_args_for_direction (xml, message_handlers[i].in_args, TRUE))
- return FALSE;
-
- if (!write_args_for_direction (xml, message_handlers[i].out_args, FALSE))
- return FALSE;
-
- if (!_dbus_string_append (xml, " </method>\n"))
- return FALSE;
-
- ++i;
- }
-
- if (!_dbus_string_append_printf (xml, " <signal name=\"NameOwnerChanged\">\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " </signal>\n"))
- return FALSE;
-
-
-
- if (!_dbus_string_append_printf (xml, " <signal name=\"NameLost\">\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " </signal>\n"))
- return FALSE;
-
+ for (mh = ih->message_handlers; mh->name != NULL; mh++)
+ {
+ if (!_dbus_string_append_printf (xml, " <method name=\"%s\">\n",
+ mh->name))
+ return FALSE;
+ if (!write_args_for_direction (xml, mh->in_args, TRUE))
+ return FALSE;
- if (!_dbus_string_append_printf (xml, " <signal name=\"NameAcquired\">\n"))
- return FALSE;
+ if (!write_args_for_direction (xml, mh->out_args, FALSE))
+ return FALSE;
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
+ if (!_dbus_string_append (xml, " </method>\n"))
+ return FALSE;
+ }
- if (!_dbus_string_append_printf (xml, " </signal>\n"))
- return FALSE;
+ if (ih->extra_introspection != NULL &&
+ !_dbus_string_append (xml, ih->extra_introspection))
+ return FALSE;
- if (!_dbus_string_append (xml, " </interface>\n"))
- return FALSE;
+ if (!_dbus_string_append (xml, " </interface>\n"))
+ return FALSE;
+ }
if (!_dbus_string_append (xml, "</node>\n"))
return FALSE;
@@ -1926,7 +1919,9 @@ bus_driver_handle_message (DBusConnection *connection,
DBusError *error)
{
const char *name, *sender, *interface;
- int i;
+ const InterfaceHandler *ih;
+ const MessageHandler *mh;
+ dbus_bool_t found_interface = FALSE;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -1944,57 +1939,50 @@ bus_driver_handle_message (DBusConnection *connection,
return TRUE; /* we just ignore this */
}
- if (dbus_message_is_method_call (message,
- DBUS_INTERFACE_INTROSPECTABLE,
- "Introspect"))
- return bus_driver_handle_introspect (connection, transaction, message, error);
-
+ /* may be NULL, which means "any interface will do" */
interface = dbus_message_get_interface (message);
- if (interface == NULL)
- interface = DBUS_INTERFACE_DBUS;
_dbus_assert (dbus_message_get_member (message) != NULL);
name = dbus_message_get_member (message);
sender = dbus_message_get_sender (message);
- if (strcmp (interface,
- DBUS_INTERFACE_DBUS) != 0)
- {
- _dbus_verbose ("Driver got message to unknown interface \"%s\"\n",
- interface);
- goto unknown;
- }
-
_dbus_verbose ("Driver got a method call: %s\n",
dbus_message_get_member (message));
/* security checks should have kept this from getting here */
_dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
- i = 0;
- while (i < _DBUS_N_ELEMENTS (message_handlers))
+ for (ih = interface_handlers; ih->name != NULL; ih++)
{
- if (strcmp (message_handlers[i].name, name) == 0)
+ if (interface != NULL && strcmp (interface, ih->name) != 0)
+ continue;
+
+ found_interface = TRUE;
+
+ for (mh = ih->message_handlers; mh->name != NULL; mh++)
{
+ if (strcmp (mh->name, name) != 0)
+ continue;
+
_dbus_verbose ("Found driver handler for %s\n", name);
- if (!dbus_message_has_signature (message, message_handlers[i].in_args))
+ if (!dbus_message_has_signature (message, mh->in_args))
{
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
_dbus_verbose ("Call to %s has wrong args (%s, expected %s)\n",
name, dbus_message_get_signature (message),
- message_handlers[i].in_args);
+ mh->in_args);
dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
"Call to %s has wrong args (%s, expected %s)\n",
name, dbus_message_get_signature (message),
- message_handlers[i].in_args);
+ mh->in_args);
_DBUS_ASSERT_ERROR_IS_SET (error);
return FALSE;
}
- if ((* message_handlers[i].handler) (connection, transaction, message, error))
+ if ((* mh->handler) (connection, transaction, message, error))
{
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
_dbus_verbose ("Driver handler succeeded\n");
@@ -2007,15 +1995,13 @@ bus_driver_handle_message (DBusConnection *connection,
return FALSE;
}
}
-
- ++i;
}
unknown:
_dbus_verbose ("No driver handler for message \"%s\"\n",
name);
- dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD,
+ dbus_set_error (error, found_interface ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_INTERFACE,
"%s does not understand message %s",
DBUS_SERVICE_DBUS, name);
diff --git a/configure.ac b/configure.ac
index 03914e17..ced95e4b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -228,6 +228,12 @@ AC_CHECK_SIZEOF(void *)
AC_CHECK_SIZEOF(long long)
AC_CHECK_SIZEOF(__int64)
+AC_ARG_WITH([64-bit],
+ [AS_HELP_STRING([--without-64-bit],
+ [If you have to use this option, please report it as a bug])],
+ [],
+ [with_64_bit=yes])
+
### See what our 64 bit type is called
AC_MSG_CHECKING([64-bit integer type])
@@ -265,13 +271,32 @@ $ac_cv_sizeof___int64)
;;
esac
-if test -z "$dbusint64" ; then
+AS_IF(
+ [test "x$with_64_bit" = xno],
+ [
DBUS_INT64_TYPE="no_int64_type_detected"
DBUS_HAVE_INT64=0
DBUS_INT64_CONSTANT=
DBUS_UINT64_CONSTANT=
- AC_MSG_RESULT([none found])
-else
+ AC_MSG_RESULT([disabled via --without-64-bit])
+ ],
+ dnl else if
+ [test -z "$dbusint64"],
+ [AC_MSG_RESULT([not found])
+ AC_MSG_ERROR([Could not find a 64-bit integer type.
+
+Please report a bug here with details of your platform and compiler:
+
+ http://bugs.freedesktop.org/enter_bug.cgi?product=DBus&component=core
+
+To compile D-Bus with all 64-bit integer types removed (not recommended), use
+the option "--without-64-bit".
+
+This option is likely to be removed in future, unless you report that your
+platform needs it.])
+ ],
+ dnl else
+ [
DBUS_INT64_TYPE="$dbusint64"
DBUS_HAVE_INT64=1
DBUS_INT64_CONSTANT="$dbusint64_constant"
@@ -280,7 +305,7 @@ else
AC_DEFINE_UNQUOTED(DBUS_INT64_PRINTF_MODIFIER, [$dbusint64_printf_modifier], [Define to printf modifier for 64 bit integer type])
fi
AC_MSG_RESULT($DBUS_INT64_TYPE)
-fi
+ ])
AC_SUBST(DBUS_INT64_TYPE)
AC_SUBST(DBUS_INT64_CONSTANT)
@@ -1745,3 +1770,16 @@ if test x$dbus_use_libxml = xtrue; then
echo
echo "WARNING: You have chosen to use libxml as your xml parser however this code path is not maintained by the D-Bus developers and if it breaks you get to keep the pieces. If you have selected this option in err please reconfigure with expat (e.g. --with-xml=expat)."
fi
+
+if test "x$DBUS_HAVE_INT64" = x0; then
+ AC_MSG_WARN([You have disabled 64-bit integers via --without-64-bit.
+
+ This removes parts of the standard D-Bus API and ABI (the 't' and 'x'
+ typecodes, the dbus_int64_t and dbus_uint64_t types, etc.) and should only be
+ used if your compiler lacks support for 64-bit integers. Please report a bug
+ with details of your platform and compiler.
+
+ This option is likely to be removed in future, unless the D-Bus developers
+ receive reports that it is still needed.
+ ])
+fi
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 6779b6ae..4a76af77 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -38,6 +38,7 @@
#include "dbus-protocol.h"
#include "dbus-dataslot.h"
#include "dbus-string.h"
+#include "dbus-signature.h"
#include "dbus-pending-call.h"
#include "dbus-object-tree.h"
#include "dbus-threads-internal.h"
@@ -3095,7 +3096,7 @@ dbus_connection_can_send_type(DBusConnection *connection,
{
_dbus_return_val_if_fail (connection != NULL, FALSE);
- if (!_dbus_type_is_valid(type))
+ if (!dbus_type_is_valid (type))
return FALSE;
if (type != DBUS_TYPE_UNIX_FD)
@@ -4522,6 +4523,7 @@ dbus_connection_dispatch (DBusConnection *connection)
DBusPendingCall *pending;
dbus_int32_t reply_serial;
DBusDispatchStatus status;
+ dbus_bool_t found_object;
_dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
@@ -4686,7 +4688,8 @@ dbus_connection_dispatch (DBusConnection *connection)
HAVE_LOCK_CHECK (connection);
result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
- message);
+ message,
+ &found_object);
CONNECTION_LOCK (connection);
@@ -4725,7 +4728,7 @@ dbus_connection_dispatch (DBusConnection *connection)
}
reply = dbus_message_new_error (message,
- DBUS_ERROR_UNKNOWN_METHOD,
+ found_object ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_OBJECT,
_dbus_string_get_const_data (&str));
_dbus_string_free (&str);
diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c
index 3cbc7216..486f1c01 100644
--- a/dbus/dbus-marshal-basic.c
+++ b/dbus/dbus-marshal-basic.c
@@ -1231,44 +1231,6 @@ _dbus_type_get_alignment (int typecode)
}
}
-
-/**
- * Return #TRUE if the typecode is a valid typecode.
- * #DBUS_TYPE_INVALID surprisingly enough is not considered valid, and
- * random unknown bytes aren't either. This function is safe with
- * untrusted data.
- *
- * @returns #TRUE if valid
- */
-dbus_bool_t
-_dbus_type_is_valid (int typecode)
-{
- switch (typecode)
- {
- case DBUS_TYPE_BYTE:
- case DBUS_TYPE_BOOLEAN:
- case DBUS_TYPE_INT16:
- case DBUS_TYPE_UINT16:
- case DBUS_TYPE_INT32:
- case DBUS_TYPE_UINT32:
- case DBUS_TYPE_INT64:
- case DBUS_TYPE_UINT64:
- case DBUS_TYPE_DOUBLE:
- case DBUS_TYPE_STRING:
- case DBUS_TYPE_OBJECT_PATH:
- case DBUS_TYPE_SIGNATURE:
- case DBUS_TYPE_ARRAY:
- case DBUS_TYPE_STRUCT:
- case DBUS_TYPE_DICT_ENTRY:
- case DBUS_TYPE_VARIANT:
- case DBUS_TYPE_UNIX_FD:
- return TRUE;
-
- default:
- return FALSE;
- }
-}
-
/**
* Returns a string describing the given type.
*
diff --git a/dbus/dbus-marshal-basic.h b/dbus/dbus-marshal-basic.h
index 0c27fc9e..3c448dff 100644
--- a/dbus/dbus-marshal-basic.h
+++ b/dbus/dbus-marshal-basic.h
@@ -254,7 +254,6 @@ dbus_uint32_t _dbus_marshal_read_uint32 (const DBusString *str,
int pos,
int byte_order,
int *new_pos);
-dbus_bool_t _dbus_type_is_valid (int typecode);
int _dbus_type_get_alignment (int typecode);
dbus_bool_t _dbus_type_is_fixed (int typecode);
int _dbus_type_get_alignment (int typecode);
diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c
index 4304467d..d87a27b9 100644
--- a/dbus/dbus-marshal-validate.c
+++ b/dbus/dbus-marshal-validate.c
@@ -250,7 +250,7 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,
if (last == DBUS_DICT_ENTRY_BEGIN_CHAR)
{
- if (!(_dbus_type_is_valid (*p) && dbus_type_is_basic (*p)))
+ if (!(dbus_type_is_valid (*p) && dbus_type_is_basic (*p)))
{
result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE;
goto out;
@@ -393,7 +393,7 @@ validate_body_helper (DBusTypeReader *reader,
{
int array_elem_type = _dbus_type_reader_get_element_type (reader);
- if (!_dbus_type_is_valid (array_elem_type))
+ if (!dbus_type_is_valid (array_elem_type))
{
return DBUS_INVALID_UNKNOWN_TYPECODE;
}
diff --git a/dbus/dbus-message-factory.c b/dbus/dbus-message-factory.c
index 7ecf8270..7fae5833 100644
--- a/dbus/dbus-message-factory.c
+++ b/dbus/dbus-message-factory.c
@@ -27,6 +27,7 @@
#ifdef DBUS_BUILD_TESTS
#include "dbus-message-factory.h"
#include "dbus-message-private.h"
+#include "dbus-signature.h"
#include "dbus-test.h"
#include <stdio.h>
@@ -978,7 +979,7 @@ find_next_typecode (DBusMessageDataIter *iter,
_dbus_assert (byte_seq < _dbus_string_get_length (data));
- if (_dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq)))
+ if (dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq)))
break;
else
iter_next (iter);
diff --git a/dbus/dbus-object-tree.c b/dbus/dbus-object-tree.c
index 28cfc8b4..989e5d8b 100644
--- a/dbus/dbus-object-tree.c
+++ b/dbus/dbus-object-tree.c
@@ -745,7 +745,8 @@ handle_default_introspect_and_unlock (DBusObjectTree *tree,
*/
DBusHandlerResult
_dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree,
- DBusMessage *message)
+ DBusMessage *message,
+ dbus_bool_t *found_object)
{
char **path;
dbus_bool_t exact_match;
@@ -791,6 +792,9 @@ _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree,
/* Find the deepest path that covers the path in the message */
subtree = find_handler (tree, (const char**) path, &exact_match);
+ if (found_object)
+ *found_object = !!subtree;
+
/* Build a list of all paths that cover the path in the message */
list = NULL;
@@ -1382,7 +1386,7 @@ do_test_dispatch (DBusObjectTree *tree,
++j;
}
- result = _dbus_object_tree_dispatch_and_unlock (tree, message);
+ result = _dbus_object_tree_dispatch_and_unlock (tree, message, NULL);
if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
goto oom;
diff --git a/dbus/dbus-object-tree.h b/dbus/dbus-object-tree.h
index 022dd93f..5576c25d 100644
--- a/dbus/dbus-object-tree.h
+++ b/dbus/dbus-object-tree.h
@@ -42,7 +42,8 @@ dbus_bool_t _dbus_object_tree_register (DBusObjectTree
void _dbus_object_tree_unregister_and_unlock (DBusObjectTree *tree,
const char **path);
DBusHandlerResult _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree,
- DBusMessage *message);
+ DBusMessage *message,
+ dbus_bool_t *found_object);
void* _dbus_object_tree_get_user_data_unlocked (DBusObjectTree *tree,
const char **path);
void _dbus_object_tree_free_all_unlocked (DBusObjectTree *tree);
diff --git a/dbus/dbus-signature.c b/dbus/dbus-signature.c
index 9c13ff43..c130de5b 100644
--- a/dbus/dbus-signature.c
+++ b/dbus/dbus-signature.c
@@ -284,7 +284,8 @@ dbus_signature_validate_single (const char *signature,
* container types. #DBUS_TYPE_INVALID is not a container type.
*
* It is an error to pass an invalid type-code, other than DBUS_TYPE_INVALID,
- * to this function. The valid type-codes are defined by dbus-protocol.h.
+ * to this function. The valid type-codes are defined by dbus-protocol.h
+ * and can be checked with dbus_type_is_valid().
*
* @param typecode either a valid type-code or DBUS_TYPE_INVALID
* @returns #TRUE if type is a container
@@ -293,7 +294,7 @@ dbus_bool_t
dbus_type_is_container (int typecode)
{
/* only reasonable (non-line-noise) typecodes are allowed */
- _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
+ _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
FALSE);
return TYPE_IS_CONTAINER (typecode);
}
@@ -307,7 +308,8 @@ dbus_type_is_container (int typecode)
* type.
*
* It is an error to pass an invalid type-code, other than DBUS_TYPE_INVALID,
- * to this function. The valid type-codes are defined by dbus-protocol.h.
+ * to this function. The valid type-codes are defined by dbus-protocol.h
+ * and can be checked with dbus_type_is_valid().
*
* @param typecode either a valid type-code or DBUS_TYPE_INVALID
* @returns #TRUE if type is basic
@@ -316,7 +318,7 @@ dbus_bool_t
dbus_type_is_basic (int typecode)
{
/* only reasonable (non-line-noise) typecodes are allowed */
- _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
+ _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
FALSE);
/* everything that isn't invalid or a container */
@@ -337,7 +339,8 @@ dbus_type_is_basic (int typecode)
* function.
*
* It is an error to pass an invalid type-code, other than DBUS_TYPE_INVALID,
- * to this function. The valid type-codes are defined by dbus-protocol.h.
+ * to this function. The valid type-codes are defined by dbus-protocol.h
+ * and can be checked with dbus_type_is_valid().
*
* @param typecode either a valid type-code or DBUS_TYPE_INVALID
* @returns #FALSE if the type can occupy different lengths
@@ -346,7 +349,7 @@ dbus_bool_t
dbus_type_is_fixed (int typecode)
{
/* only reasonable (non-line-noise) typecodes are allowed */
- _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
+ _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
FALSE);
switch (typecode)
@@ -367,6 +370,44 @@ dbus_type_is_fixed (int typecode)
}
}
+/**
+ * Return #TRUE if the argument is a valid typecode.
+ * #DBUS_TYPE_INVALID surprisingly enough is not considered valid, and
+ * random unknown bytes aren't either. This function is safe with
+ * untrusted data.
+ *
+ * @param typecode a potential type-code
+ * @returns #TRUE if valid
+ */
+dbus_bool_t
+dbus_type_is_valid (int typecode)
+{
+ switch (typecode)
+ {
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ case DBUS_TYPE_DOUBLE:
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_SIGNATURE:
+ case DBUS_TYPE_ARRAY:
+ case DBUS_TYPE_STRUCT:
+ case DBUS_TYPE_DICT_ENTRY:
+ case DBUS_TYPE_VARIANT:
+ case DBUS_TYPE_UNIX_FD:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
/** @} */ /* end of DBusSignature group */
#ifdef DBUS_BUILD_TESTS
diff --git a/dbus/dbus-signature.h b/dbus/dbus-signature.h
index ebf00c1e..443941c8 100644
--- a/dbus/dbus-signature.h
+++ b/dbus/dbus-signature.h
@@ -79,6 +79,9 @@ dbus_bool_t dbus_signature_validate_single (const char *signatur
DBusError *error);
DBUS_EXPORT
+dbus_bool_t dbus_type_is_valid (int typecode);
+
+DBUS_EXPORT
dbus_bool_t dbus_type_is_basic (int typecode);
DBUS_EXPORT
dbus_bool_t dbus_type_is_container (int typecode);
diff --git a/dbus/dbus-string-util.c b/dbus/dbus-string-util.c
index 4d42bb0b..b31703ca 100644
--- a/dbus/dbus-string-util.c
+++ b/dbus/dbus-string-util.c
@@ -266,7 +266,7 @@ _dbus_string_test (void)
{
DBusString str;
DBusString other;
- int i, end;
+ int i, a, end;
long v;
double d;
int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 };
@@ -513,10 +513,94 @@ _dbus_string_test (void)
_dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
_dbus_assert (_dbus_string_equal_c_str (&other,
"HelloHello WorldWorle"));
-
+
_dbus_string_free (&str);
_dbus_string_free (&other);
+
+ /* Different tests are provided because different behaviours are
+ * implemented in _dbus_string_replace_len() in function of replacing and
+ * replaced lengths
+ */
+
+ if (!_dbus_string_init (&str))
+ _dbus_assert_not_reached ("failed to init string");
+ if (!_dbus_string_append (&str, "Hello World"))
+ _dbus_assert_not_reached ("could not append to string");
+
+ i = _dbus_string_get_length (&str);
+
+ if (!_dbus_string_init (&other))
+ _dbus_assert_not_reached ("could not init string");
+
+ if (!_dbus_string_append (&other, "Foo String"))
+ _dbus_assert_not_reached ("could not append to string");
+
+ a = _dbus_string_get_length (&other);
+
+ if (!_dbus_string_replace_len (&str, 0, 6,
+ &other, 4, 0))
+ _dbus_assert_not_reached ("could not replace 0 length");
+
+ _dbus_assert (_dbus_string_get_length (&str) == i);
+ _dbus_assert (_dbus_string_get_length (&other) == a + 6);
+ _dbus_assert (_dbus_string_equal_c_str (&other,
+ "Foo Hello String"));
+
+ if (!_dbus_string_replace_len (&str, 5, 6,
+ &other,
+ _dbus_string_get_length (&other),
+ 0))
+ _dbus_assert_not_reached ("could not replace at the end");
+
+ _dbus_assert (_dbus_string_get_length (&str) == i);
+ _dbus_assert (_dbus_string_get_length (&other) == a + 6 + 6);
+ _dbus_assert (_dbus_string_equal_c_str (&other,
+ "Foo Hello String World"));
+
+ if (!_dbus_string_replace_len (&str, 0, 5,
+ &other,
+ _dbus_string_get_length (&other) - 5,
+ 5))
+ _dbus_assert_not_reached ("could not replace same length");
+
+ _dbus_assert (_dbus_string_get_length (&str) == i);
+ _dbus_assert (_dbus_string_get_length (&other) == a + 6 + 6);
+ _dbus_assert (_dbus_string_equal_c_str (&other,
+ "Foo Hello String Hello"));
+
+ if (!_dbus_string_replace_len (&str, 6, 5,
+ &other, 4, 12))
+ _dbus_assert_not_reached ("could not replace with shorter string");
+
+ _dbus_assert (_dbus_string_get_length (&str) == i);
+ _dbus_assert (_dbus_string_get_length (&other) == a + 5);
+ _dbus_assert (_dbus_string_equal_c_str (&other,
+ "Foo World Hello"));
+
+ if (!_dbus_string_replace_len (&str, 0, 1,
+ &other, 0, 3))
+ _dbus_assert_not_reached ("could not replace at the beginning");
+
+ _dbus_assert (_dbus_string_get_length (&str) == i);
+ _dbus_assert (_dbus_string_get_length (&other) == a + 3);
+ _dbus_assert (_dbus_string_equal_c_str (&other,
+ "H World Hello"));
+
+ if (!_dbus_string_replace_len (&str, 6, 5,
+ &other,
+ _dbus_string_get_length (&other) - 5,
+ 5))
+ _dbus_assert_not_reached ("could not replace same length");
+
+ _dbus_assert (_dbus_string_get_length (&str) == i);
+ _dbus_assert (_dbus_string_get_length (&other) == a + 3);
+ _dbus_assert (_dbus_string_equal_c_str (&other,
+ "H World World"));
+
+ _dbus_string_free (&str);
+ _dbus_string_free (&other);
+
/* Check append/get unichar */
if (!_dbus_string_init (&str))
diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c
index e2eb93b9..2471f46d 100644
--- a/dbus/dbus-string.c
+++ b/dbus/dbus-string.c
@@ -1635,15 +1635,6 @@ _dbus_string_copy_len (const DBusString *source,
/**
* Replaces a segment of dest string with a segment of source string.
*
- * @todo optimize the case where the two lengths are the same, and
- * avoid memmoving the data in the trailing part of the string twice.
- *
- * @todo avoid inserting the source into dest, then deleting
- * the replaced chunk of dest (which creates a potentially large
- * intermediate string). Instead, extend the replaced chunk
- * of dest with padding to the same size as the source chunk,
- * then copy in the source bytes.
- *
* @param source the source string
* @param start where to start copying the source string
* @param len length of segment to copy
@@ -1669,11 +1660,37 @@ _dbus_string_replace_len (const DBusString *source,
_dbus_assert (replace_at <= real_dest->len);
_dbus_assert (replace_len <= real_dest->len - replace_at);
- if (!copy (real_source, start, len,
- real_dest, replace_at))
- return FALSE;
+ if (len == replace_len)
+ {
+ memmove (real_dest->str + replace_at,
+ real_source->str + start, len);
+ }
+ else if (len < replace_len)
+ {
+ memmove (real_dest->str + replace_at,
+ real_source->str + start, len);
+ delete (real_dest, replace_at + len,
+ replace_len - len);
+ }
+ else
+ {
+ int diff;
- delete (real_dest, replace_at + len, replace_len);
+ _dbus_assert (len > replace_len);
+
+ diff = len - replace_len;
+
+ /* First of all we check if destination string can be enlarged as
+ * required, then we overwrite previous bytes
+ */
+
+ if (!copy (real_source, start + replace_len, diff,
+ real_dest, replace_at + replace_len))
+ return FALSE;
+
+ memmove (real_dest->str + replace_at,
+ real_source->str + start, replace_len);
+ }
return TRUE;
}
diff --git a/test/break-loader.c b/test/break-loader.c
index 7bfa7227..542f36ff 100644
--- a/test/break-loader.c
+++ b/test/break-loader.c
@@ -446,7 +446,7 @@ randomly_change_one_type (const DBusString *orig_data,
{
int b;
b = _dbus_string_get_byte (mutated, i);
- if (_dbus_type_is_valid (b))
+ if (dbus_type_is_valid (b))
{
_dbus_string_set_byte (mutated, i, random_type ());
return;