summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott James Remnant <scott@ubuntu.com>2009-07-09 16:34:54 +0100
committerColin Walters <walters@verbum.org>2009-07-14 15:39:11 -0400
commit2ff4bc2513db5a0c64297fbf4c5a8486c737a12a (patch)
tree3b1276178c7d0c19060baf61f4418825fe8e9b2d
parentbf2183345fbd19632e81b107593ca4e944d798de (diff)
downloaddbus-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.c4
-rw-r--r--dbus/dbus-message.c55
-rw-r--r--dbus/dbus-message.h2
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);