diff options
Diffstat (limited to 'dbus/dbus-message.c')
-rw-r--r-- | dbus/dbus-message.c | 80 |
1 files changed, 77 insertions, 3 deletions
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index d8d746a6..33732292 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ @@ -1722,8 +1722,10 @@ dbus_message_append_args_valist (DBusMessage *message, if (!dbus_message_iter_append_fixed_array (&array, element_type, value, - n_elements)) + n_elements)) { + dbus_message_iter_abandon_container (&iter, &array); goto failed; + } } else if (element_type == DBUS_TYPE_STRING || element_type == DBUS_TYPE_SIGNATURE || @@ -1744,8 +1746,10 @@ dbus_message_append_args_valist (DBusMessage *message, { if (!dbus_message_iter_append_basic (&array, element_type, - &value[i])) + &value[i])) { + dbus_message_iter_abandon_container (&iter, &array); goto failed; + } ++i; } } @@ -2397,6 +2401,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) @@ -2710,6 +2743,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 @@ -4413,6 +4472,7 @@ dbus_message_marshal (DBusMessage *msg, int *len_p) { DBusString tmp; + dbus_bool_t was_locked; _dbus_return_val_if_fail (msg != NULL, FALSE); _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE); @@ -4421,6 +4481,12 @@ dbus_message_marshal (DBusMessage *msg, if (!_dbus_string_init (&tmp)) return FALSE; + /* Ensure the message is locked, to ensure the length header is filled in. */ + was_locked = msg->locked; + + if (!was_locked) + dbus_message_lock (msg); + if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0)) goto fail; @@ -4435,10 +4501,18 @@ dbus_message_marshal (DBusMessage *msg, goto fail; _dbus_string_free (&tmp); + + if (!was_locked) + msg->locked = FALSE; + return TRUE; fail: _dbus_string_free (&tmp); + + if (!was_locked) + msg->locked = FALSE; + return FALSE; } |