diff --git a/dbus/dbus-message-util.c b/dbus/dbus-message-util.c index 0fa010c..562190a 100644 --- a/dbus/dbus-message-util.c +++ b/dbus/dbus-message-util.c @@ -1226,6 +1226,7 @@ _dbus_message_test (const char *test_data_dir) DBusError error = DBUS_ERROR_INIT; char *marshalled = NULL; int len = 0; + char garbage_header[DBUS_MINIMUM_HEADER_SIZE] = "xxx"; if (!dbus_message_marshal (message, &marshalled, &len)) _dbus_assert_not_reached ("failed to marshal message"); @@ -1233,6 +1234,7 @@ _dbus_message_test (const char *test_data_dir) _dbus_assert (len != 0); _dbus_assert (marshalled != NULL); + _dbus_assert (dbus_message_demarshal_bytes_needed (marshalled, len) == len); message2 = dbus_message_demarshal (marshalled, len, &error); _dbus_assert (message2 != NULL); @@ -1255,6 +1257,14 @@ _dbus_message_test (const char *test_data_dir) _dbus_assert (message2 == NULL); _dbus_assert (dbus_error_is_set (&error)); dbus_error_free (&error); + + /* Bytes needed to demarshal empty message: 0 (more) */ + + _dbus_assert (dbus_message_demarshal_bytes_needed ("", 0) == 0); + + /* Bytes needed to demarshal invalid message: -1 (error). */ + + _dbus_assert (dbus_message_demarshal_bytes_needed (garbage_header, DBUS_MINIMUM_HEADER_SIZE) == -1); } dbus_message_unref (message); diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index cd44798..2871e5f 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -3941,6 +3941,9 @@ dbus_message_marshal (DBusMessage *msg, _dbus_return_val_if_fail (msg != NULL, FALSE); _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE); _dbus_return_val_if_fail (len_p != NULL, FALSE); + + /* Lock the message, if it isn't already. */ + _dbus_message_lock (msg); if (!_dbus_string_init (&tmp)) return FALSE; @@ -4023,6 +4026,62 @@ dbus_message_demarshal (const char *str, return NULL; } +/** + * Returns the number of bytes required to be in the buffer to demarshal a + * D-Bus message. + * + * Generally, this function is only useful for encapsulating D-Bus messages in + * a different protocol. + * + * @param str data to be marshalled + * @param len the length of str + * @param error the location to save errors to + * @returns -1 if there was an error, 0 if there wasn't enough data to determine how much should be demarshalled. Otherwise returns the number of bytes to be demarshalled + * + */ +int +dbus_message_demarshal_bytes_needed(const char *str, + int len) +{ + DBusString strtmp; + int byte_order, fields_array_len, header_len, body_len; + DBusValidity validity = DBUS_VALID; + int have_message; + + if (!str || len < DBUS_MINIMUM_HEADER_SIZE) + return 0; + + if (len > DBUS_MAXIMUM_MESSAGE_LENGTH) + len = DBUS_MAXIMUM_MESSAGE_LENGTH; + + if (!_dbus_string_init (&strtmp)) + return -1; + + _dbus_string_append_len (&strtmp, str, len); + + validity = DBUS_VALID; + have_message + = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH, + &validity, &byte_order, + &fields_array_len, + &header_len, + &body_len, + &strtmp, 0, + len); + _dbus_string_free (&strtmp); + + if (have_message || validity == DBUS_VALID) + return header_len + body_len; + else + { + return -1; /* broken! */ + } +} + /** @} */ /* tests in dbus-message-util.c */ diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index 1bf7d0c..d4e0799 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -220,6 +220,8 @@ DBusMessage* dbus_message_demarshal (const char *str, int len, DBusError *error); +int dbus_message_demarshal_bytes_needed (const char *str, int len); + /** @} */ DBUS_END_DECLS