summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-message.c
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-01-19 03:33:35 +0000
committerHavoc Pennington <hp@redhat.com>2003-01-19 03:33:35 +0000
commit502fbda2201a4e7e50d687f42af29c82e66299bb (patch)
tree39aef7adb025c95dd016714dffd8577402a4669a /dbus/dbus-message.c
parent0363701c341796278041fb9ea7de80eaaf41479a (diff)
2003-01-18 Havoc Pennington <hp@pobox.com>
* dbus/dbus-transport-unix.c (unix_do_iteration): only do the reading/writing if read_watch != NULL or write_watch != NULL. * dbus/dbus-message.c (_dbus_message_loader_return_buffer): fix the message loader code to actually load message->header and message->body into the newly-created message. * dbus/dbus-transport-unix.c (check_write_watch): fix a mem leak in OOM case * dbus/dbus-connection.c (dbus_connection_set_max_message_size) (dbus_connection_get_max_message_size) (dbus_connection_set_max_live_messages_size) (dbus_connection_get_max_live_messages_size): implement some resource limitation functions * dbus/dbus-resources.c: new file implementing some of the resource limits stuff * dbus/dbus-message.c (dbus_message_iter_get_byte_array): add missing docs, add @todo to handle OOM etc. * dbus/dbus-marshal.c (_dbus_demarshal_byte_array): add missing docs
Diffstat (limited to 'dbus/dbus-message.c')
-rw-r--r--dbus/dbus-message.c148
1 files changed, 128 insertions, 20 deletions
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index 3bd92803..6206815f 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -1,7 +1,7 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-message.c DBusMessage object
*
- * Copyright (C) 2002 Red Hat Inc.
+ * Copyright (C) 2002, 2003 Red Hat Inc.
* Copyright (C) 2002, 2003 CodeFactory AB
*
* Licensed under the Academic Free License version 1.2
@@ -41,13 +41,6 @@
*/
/**
- * The largest-length message we allow
- *
- * @todo match this up with whatever the protocol spec says.
- */
-#define _DBUS_MAX_MESSAGE_LENGTH (_DBUS_INT_MAX/16)
-
-/**
* @brief Internals of DBusMessage
*
* Object representing a message received from or to be sent to
@@ -72,6 +65,9 @@ struct DBusMessage
dbus_int32_t client_serial; /**< Client serial or -1 if not set */
dbus_int32_t reply_serial; /**< Reply serial or -1 if not set */
+
+ DBusCounter *size_counter; /**< Counter for the size of the message, or #NULL */
+ long size_counter_delta; /**< Size we incremented the size counter by. */
unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
};
@@ -127,6 +123,39 @@ _dbus_message_set_client_serial (DBusMessage *message,
message->client_serial = client_serial;
}
+/**
+ * Adds a counter to be incremented immediately with the
+ * size of this message, and decremented by the size
+ * of this message when this message if finalized.
+ *
+ * @param message the message
+ * @param counter the counter
+ */
+void
+_dbus_message_add_size_counter (DBusMessage *message,
+ DBusCounter *counter)
+{
+ _dbus_assert (message->size_counter == NULL); /* If this fails we may need to keep a list of
+ * counters instead of just one
+ */
+
+ message->size_counter = counter;
+ _dbus_counter_ref (message->size_counter);
+
+ /* When we can change message size, we may want to
+ * update this each time we do so, or we may want to
+ * just KISS like this.
+ */
+ message->size_counter_delta =
+ _dbus_string_get_length (&message->header) +
+ _dbus_string_get_length (&message->body);
+
+ _dbus_verbose ("message has size %ld\n",
+ message->size_counter_delta);
+
+ _dbus_counter_adjust (message->size_counter, message->size_counter_delta);
+}
+
static void
dbus_message_write_header (DBusMessage *message)
{
@@ -253,7 +282,7 @@ dbus_message_new (const char *service,
message->client_serial = -1;
message->reply_serial = -1;
- if (!_dbus_string_init (&message->header, _DBUS_MAX_MESSAGE_LENGTH))
+ if (!_dbus_string_init (&message->header, _DBUS_INT_MAX))
{
dbus_free (message->service);
dbus_free (message->name);
@@ -261,7 +290,7 @@ dbus_message_new (const char *service,
return NULL;
}
- if (!_dbus_string_init (&message->body, _DBUS_MAX_MESSAGE_LENGTH))
+ if (!_dbus_string_init (&message->body, _DBUS_INT_MAX))
{
dbus_free (message->service);
dbus_free (message->name);
@@ -302,6 +331,13 @@ dbus_message_unref (DBusMessage *message)
message->refcount -= 1;
if (message->refcount == 0)
{
+ if (message->size_counter != NULL)
+ {
+ _dbus_counter_adjust (message->size_counter,
+ - message->size_counter_delta);
+ _dbus_counter_unref (message->size_counter);
+ }
+
_dbus_string_free (&message->header);
_dbus_string_free (&message->body);
@@ -330,7 +366,7 @@ dbus_message_get_name (DBusMessage *message)
* The list is terminated with 0.
*
* @param message the message
- * @param type of the first field
+ * @param first_field_type type of the first field
* @param ... value of first field, list of additional type-value pairs
* @returns #TRUE on success
*/
@@ -886,8 +922,21 @@ dbus_message_iter_get_double (DBusMessageIter *iter)
iter->pos + 1, NULL);
}
+/**
+ * Returns the byte array that the iterator may point to.
+ * Note that you need to check that the iterator points
+ * to a byte array prior to using this function.
+ *
+ * @todo this function should probably take "unsigned char **" as
+ * an out param argument, and return boolean or result code.
+ *
+ * @param iter the iterator
+ * @param len return location for length of byte array
+ * @returns the byte array
+ */
unsigned char *
-dbus_message_iter_get_byte_array (DBusMessageIter *iter, int *len)
+dbus_message_iter_get_byte_array (DBusMessageIter *iter,
+ int *len)
{
_dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_BYTE_ARRAY);
@@ -926,6 +975,8 @@ struct DBusMessageLoader
DBusString data; /**< Buffered data */
DBusList *messages; /**< Complete messages. */
+
+ long max_message_size; /**< Maximum size of a message */
unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
@@ -959,8 +1010,13 @@ _dbus_message_loader_new (void)
if (loader == NULL)
return NULL;
- loader->refcount = 1;
+ loader->refcount = 1;
+ /* Try to cap message size at something that won't *totally* hose
+ * the system if we have a couple of them.
+ */
+ loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
+
if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX))
{
dbus_free (loader);
@@ -1190,10 +1246,10 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
header_len = _dbus_unpack_int32 (byte_order, header_data + 4);
body_len = _dbus_unpack_int32 (byte_order, header_data + 8);
- if (header_len + body_len > _DBUS_MAX_MESSAGE_LENGTH)
+ if (header_len + body_len > loader->max_message_size)
{
_dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %d\n",
- header_len, body_len, _DBUS_MAX_MESSAGE_LENGTH);
+ header_len, body_len, loader->max_message_size);
loader->corrupted = TRUE;
return;
}
@@ -1220,13 +1276,40 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
if (message == NULL)
break; /* ugh, postpone this I guess. */
+
+ if (!_dbus_list_append (&loader->messages, message))
+ {
+ dbus_message_unref (message);
+ break;
+ }
- _dbus_string_copy (&loader->data, header_len, &message->body, 0);
- _dbus_message_set_client_serial (message, client_serial);
-
- _dbus_list_append (&loader->messages, message);
- _dbus_string_delete (&loader->data, 0, header_len + body_len);
+ _dbus_assert (_dbus_string_get_length (&message->header) == 0);
+ _dbus_assert (_dbus_string_get_length (&message->body) == 0);
+
+ if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
+ {
+ _dbus_list_remove_last (&loader->messages, message);
+ dbus_message_unref (message);
+ break;
+ }
+
+ if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
+ {
+ dbus_bool_t result;
+
+ /* put the header back, we'll try again later */
+ result = _dbus_string_copy_len (&message->header, 0, header_len,
+ &loader->data, 0);
+ _dbus_assert (result); /* because DBusString never reallocs smaller */
+ _dbus_list_remove_last (&loader->messages, message);
+ dbus_message_unref (message);
+ break;
+ }
+
+ _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
+ _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
+
_dbus_verbose ("Loaded message %p\n", message);
}
else
@@ -1264,6 +1347,31 @@ _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
return loader->corrupted;
}
+/**
+ * Sets the maximum size message we allow.
+ *
+ * @param loader the loader
+ * @param size the max message size in bytes
+ */
+void
+_dbus_message_loader_set_max_message_size (DBusMessageLoader *loader,
+ long size)
+{
+ loader->max_message_size = size;
+}
+
+/**
+ * Gets the maximum allowed message size in bytes.
+ *
+ * @param loader the loader
+ * @returns max size in bytes
+ */
+long
+_dbus_message_loader_get_max_message_size (DBusMessageLoader *loader)
+{
+ return loader->max_message_size;
+}
+
/** @} */
#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"