diff options
author | Scott James Remnant <scott@ubuntu.com> | 2009-07-09 16:34:54 +0100 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2009-07-14 15:39:11 -0400 |
commit | 2ff4bc2513db5a0c64297fbf4c5a8486c737a12a (patch) | |
tree | 3b1276178c7d0c19060baf61f4418825fe8e9b2d | |
parent | bf2183345fbd19632e81b107593ca4e944d798de (diff) | |
download | dbus-2ff4bc2513db5a0c64297fbf4c5a8486c737a12a.tar.gz |
bfo22316 - add dbus_message_iter_abandon_container()
It's not currently possible to abandon creation of a container without
either hitting asserts or leaking memory. This new function allows
that.
Signed-off-by: Scott James Remnant <scott@ubuntu.com>
(cherry picked from commit e57a368c440aec39caf6c3b491cf76ef615dc2e8)
-rw-r--r-- | dbus/dbus-message-util.c | 4 | ||||
-rw-r--r-- | dbus/dbus-message.c | 55 | ||||
-rw-r--r-- | dbus/dbus-message.h | 2 |
3 files changed, 59 insertions, 2 deletions
diff --git a/dbus/dbus-message-util.c b/dbus/dbus-message-util.c index 3d5a00f5..b995f5ee 100644 --- a/dbus/dbus-message-util.c +++ b/dbus/dbus-message-util.c @@ -1296,8 +1296,8 @@ _dbus_message_test (const char *test_data_dir) /* uh-oh, error, try and unwind */ - _dbus_assert (dbus_message_iter_close_container (&array_iter, &struct_iter)); - _dbus_assert (dbus_message_iter_close_container (&array_iter, &iter)); + dbus_message_iter_abandon_container (&array_iter, &struct_iter); + dbus_message_iter_abandon_container (&array_iter, &iter); dbus_message_unref (message); diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index edae4258..30b5d6c0 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -2200,6 +2200,35 @@ _dbus_message_iter_close_signature (DBusMessageRealIter *real) return retval; } +/** + * Frees the signature string and marks the iterator as not having a + * type_str anymore. Since the new signature is not set, the message + * will generally be hosed after this is called. + * + * @param real an iterator without a type_str + */ +static void +_dbus_message_iter_abandon_signature (DBusMessageRealIter *real) +{ + DBusString *str; + + _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); + _dbus_assert (real->u.writer.type_str != NULL); + _dbus_assert (real->sig_refcount > 0); + + real->sig_refcount -= 1; + + if (real->sig_refcount > 0) + return; + _dbus_assert (real->sig_refcount == 0); + + str = real->u.writer.type_str; + + _dbus_type_writer_remove_types (&real->u.writer); + _dbus_string_free (str); + dbus_free (str); +} + #ifndef DBUS_DISABLE_CHECKS static dbus_bool_t _dbus_message_iter_append_check (DBusMessageRealIter *iter) @@ -2428,6 +2457,32 @@ dbus_message_iter_close_container (DBusMessageIter *iter, } /** + * Abandons creation of a contained-typed value and frees resources created + * by dbus_message_iter_open_container(). Once this returns, the message + * is hosed and you have to start over building the whole message. + * + * This should only be used to abandon creation of a message when you have + * open containers. + * + * @param iter the append iterator + * @param sub sub-iterator to close + */ +void +dbus_message_iter_abandon_container (DBusMessageIter *iter, + DBusMessageIter *sub) +{ + DBusMessageRealIter *real = (DBusMessageRealIter *)iter; + DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; + + _dbus_return_if_fail (_dbus_message_iter_append_check (real)); + _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); + _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub)); + _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); + + _dbus_message_iter_abandon_signature (real); +} + +/** * Sets a flag indicating that the message does not want a reply; if * this flag is set, the other end of the connection may (but is not * required to) optimize by not sending method return or error diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index 2e29fef0..49c7e721 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -197,6 +197,8 @@ dbus_bool_t dbus_message_iter_open_container (DBusMessageIter *iter, DBusMessageIter *sub); dbus_bool_t dbus_message_iter_close_container (DBusMessageIter *iter, DBusMessageIter *sub); +void dbus_message_iter_abandon_container (DBusMessageIter *iter, + DBusMessageIter *sub); void dbus_message_lock (DBusMessage *message); |