diff options
-rw-r--r-- | NEWS | 14 | ||||
-rw-r--r-- | bus/driver.c | 184 | ||||
-rw-r--r-- | configure.ac | 46 | ||||
-rw-r--r-- | dbus/dbus-connection.c | 9 | ||||
-rw-r--r-- | dbus/dbus-marshal-basic.c | 38 | ||||
-rw-r--r-- | dbus/dbus-marshal-basic.h | 1 | ||||
-rw-r--r-- | dbus/dbus-marshal-validate.c | 4 | ||||
-rw-r--r-- | dbus/dbus-message-factory.c | 3 | ||||
-rw-r--r-- | dbus/dbus-object-tree.c | 8 | ||||
-rw-r--r-- | dbus/dbus-object-tree.h | 3 | ||||
-rw-r--r-- | dbus/dbus-signature.c | 53 | ||||
-rw-r--r-- | dbus/dbus-signature.h | 3 | ||||
-rw-r--r-- | dbus/dbus-string-util.c | 88 | ||||
-rw-r--r-- | dbus/dbus-string.c | 43 | ||||
-rw-r--r-- | test/break-loader.c | 2 |
15 files changed, 326 insertions, 173 deletions
@@ -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; |