summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2005-01-02 00:37:24 +0000
committerHavoc Pennington <hp@redhat.com>2005-01-02 00:37:24 +0000
commit441907e73affff202c75564f4c4b968ff37f094b (patch)
tree7cb58d850facd9508a276276522a3402f7b8eeb3
parenta6580a59402ca09499f907601ad6535394e197f2 (diff)
add DBusTypeMark
-rw-r--r--dbus/dbus-marshal-basic.h4
-rw-r--r--dbus/dbus-marshal-recursive.c230
-rw-r--r--dbus/dbus-marshal-recursive.h74
-rw-r--r--dbus/dbus-protocol-new.h32
4 files changed, 272 insertions, 68 deletions
diff --git a/dbus/dbus-marshal-basic.h b/dbus/dbus-marshal-basic.h
index 992e6764..9e78aa84 100644
--- a/dbus/dbus-marshal-basic.h
+++ b/dbus/dbus-marshal-basic.h
@@ -104,6 +104,10 @@
#define DBUS_STRUCT_END_CHAR_AS_STRING ")"
#define DBUS_MAXIMUM_SIGNATURE_LENGTH 255
+#define DBUS_MAXIMUM_ARRAY_LENGTH (67108864)
+#define DBUS_MAXIMUM_ARRAY_LENGTH_BITS 26
+#define DBUS_MAXIMUM_MESSAGE_LENGTH (DBUS_MAXIMUM_ARRAY_LENGTH * 2)
+#define DBUS_MAXIMUM_MESSAGE_LENGTH_BITS 27
static const char *
_hack_dbus_type_to_string (int type)
diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c
index 0bf59ed1..a01b254b 100644
--- a/dbus/dbus-marshal-recursive.c
+++ b/dbus/dbus-marshal-recursive.c
@@ -34,12 +34,15 @@
struct DBusTypeReaderClass
{
const char *name;
+ int id; /* index in all_reader_classes */
dbus_bool_t types_only; /* only iterates over types, not values */
- void (* recurse) (DBusTypeReader *sub,
- DBusTypeReader *parent);
- int (* get_current_type) (DBusTypeReader *reader);
- void (* next) (DBusTypeReader *reader,
- int current_type);
+ void (* recurse) (DBusTypeReader *sub,
+ DBusTypeReader *parent);
+ int (* get_current_type) (DBusTypeReader *reader);
+ void (* next) (DBusTypeReader *reader,
+ int current_type);
+ void (* init_from_mark) (DBusTypeReader *reader,
+ const DBusTypeMark *mark);
};
static int
@@ -123,20 +126,40 @@ array_types_only_reader_recurse (DBusTypeReader *sub,
/* point type_pos at the array element type */
sub->type_pos += 1;
- sub->u.array.element_type = first_type_in_signature (sub->type_str,
- sub->type_pos);
-
/* Init with values likely to crash things if misused */
sub->u.array.start_pos = _DBUS_INT_MAX;
- sub->u.array.len = _DBUS_INT_MAX;
+ sub->array_len_offset = 7;
+}
+
+static int
+array_reader_get_array_len (DBusTypeReader *reader)
+{
+ dbus_uint32_t array_len;
+ int len_pos;
+
+ /* array_len_offset is the offset back from start_pos to end of the len */
+ len_pos = reader->u.array.start_pos - ((int)reader->array_len_offset) - 4;
+
+ _dbus_demarshal_basic_type (reader->value_str,
+ DBUS_TYPE_UINT32,
+ &array_len,
+ reader->byte_order,
+ len_pos, NULL);
+
+ _dbus_verbose (" reader %p len_pos %d array len %u len_offset %d\n",
+ reader, len_pos, array_len, reader->array_len_offset);
+
+ _dbus_assert (reader->u.array.start_pos - len_pos - 4 < 8);
+
+ return array_len;
}
static void
array_reader_recurse (DBusTypeReader *sub,
DBusTypeReader *parent)
{
- dbus_uint32_t array_len;
int alignment;
+ int len_pos;
_dbus_assert (!_dbus_type_reader_array_is_empty (parent));
@@ -144,28 +167,27 @@ array_reader_recurse (DBusTypeReader *sub,
sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
- _dbus_demarshal_basic_type (sub->value_str,
- DBUS_TYPE_UINT32,
- &array_len,
- sub->byte_order,
- sub->value_pos,
- &sub->value_pos);
-
- sub->u.array.len = array_len;
+ len_pos = sub->value_pos;
+ sub->value_pos += 4; /* for the length */
+
alignment = element_type_get_alignment (sub->type_str,
sub->type_pos);
sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
sub->u.array.start_pos = sub->value_pos;
+ _dbus_assert ((sub->u.array.start_pos - (len_pos + 4)) < 8); /* only 3 bits in array_len_offset */
+ sub->array_len_offset = sub->u.array.start_pos - (len_pos + 4);
#if RECURSIVE_MARSHAL_TRACE
- _dbus_verbose (" type reader %p array start = %d array len = %d array element type = %s\n",
+ _dbus_verbose (" type reader %p array start = %d len_offset = %d array len = %d array element type = %s\n",
sub,
sub->u.array.start_pos,
- sub->u.array.len,
- _dbus_type_to_string (sub->u.array.element_type));
+ sub->array_len_offset,
+ array_reader_get_array_len (sub),
+ _dbus_type_to_string (first_type_in_signature (sub->type_str,
+ sub->type_pos)));
#endif
}
@@ -231,7 +253,8 @@ array_types_only_reader_get_current_type (DBusTypeReader *reader)
if (reader->finished)
t = DBUS_TYPE_INVALID;
else
- t = reader->u.array.element_type;
+ t = first_type_in_signature (reader->type_str,
+ reader->type_pos);
return t;
}
@@ -246,13 +269,14 @@ array_reader_get_current_type (DBusTypeReader *reader)
* TYPE_INVALID otherwise
*/
- end_pos = reader->u.array.start_pos + reader->u.array.len;
+ end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
_dbus_assert (reader->value_pos <= end_pos);
_dbus_assert (reader->value_pos >= reader->u.array.start_pos);
if (reader->value_pos < end_pos)
- t = reader->u.array.element_type;
+ t = first_type_in_signature (reader->type_str,
+ reader->type_pos);
else
t = DBUS_TYPE_INVALID;
@@ -391,12 +415,13 @@ array_reader_next (DBusTypeReader *reader,
/* Skip one array element */
int end_pos;
- end_pos = reader->u.array.start_pos + reader->u.array.len;
+ end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
_dbus_assert (reader->value_pos < end_pos);
_dbus_assert (reader->value_pos >= reader->u.array.start_pos);
- switch (reader->u.array.element_type)
+ switch (first_type_in_signature (reader->type_str,
+ reader->type_pos))
{
case DBUS_TYPE_STRUCT:
case DBUS_TYPE_VARIANT:
@@ -444,60 +469,89 @@ array_reader_next (DBusTypeReader *reader,
}
}
+static void
+array_init_from_mark (DBusTypeReader *reader,
+ const DBusTypeMark *mark)
+{
+ /* Fill in the array-specific fields from the mark. The general
+ * fields are already filled in.
+ */
+ reader->u.array.start_pos = mark->array_start_pos;
+ reader->array_len_offset = mark->array_len_offset;
+}
+
static const DBusTypeReaderClass body_reader_class = {
- "body",
+ "body", 0,
FALSE,
NULL, /* body is always toplevel, so doesn't get recursed into */
base_reader_get_current_type,
- base_reader_next
+ base_reader_next,
+ NULL
};
static const DBusTypeReaderClass body_types_only_reader_class = {
- "body types",
+ "body types", 1,
TRUE,
NULL, /* body is always toplevel, so doesn't get recursed into */
base_reader_get_current_type,
- base_reader_next
+ base_reader_next,
+ NULL
};
static const DBusTypeReaderClass struct_reader_class = {
- "struct",
+ "struct", 2,
FALSE,
struct_reader_recurse,
struct_reader_get_current_type,
- struct_reader_next
+ struct_reader_next,
+ NULL
};
static const DBusTypeReaderClass struct_types_only_reader_class = {
- "struct types",
+ "struct types", 3,
TRUE,
struct_types_only_reader_recurse,
struct_reader_get_current_type,
- struct_reader_next
+ struct_reader_next,
+ NULL
};
static const DBusTypeReaderClass array_reader_class = {
- "array",
+ "array", 4,
FALSE,
array_reader_recurse,
array_reader_get_current_type,
- array_reader_next
+ array_reader_next,
+ array_init_from_mark
};
static const DBusTypeReaderClass array_types_only_reader_class = {
- "array types",
+ "array types", 5,
TRUE,
array_types_only_reader_recurse,
array_types_only_reader_get_current_type,
- array_types_only_reader_next
+ array_types_only_reader_next,
+ NULL
};
static const DBusTypeReaderClass variant_reader_class = {
- "variant",
+ "variant", 6,
FALSE,
variant_reader_recurse,
base_reader_get_current_type,
- base_reader_next
+ base_reader_next,
+ NULL
+};
+
+static const DBusTypeReaderClass const *
+all_reader_classes[] = {
+ &body_reader_class,
+ &body_types_only_reader_class,
+ &struct_reader_class,
+ &struct_types_only_reader_class,
+ &array_reader_class,
+ &array_types_only_reader_class,
+ &variant_reader_class
};
void
@@ -521,6 +575,30 @@ _dbus_type_reader_init (DBusTypeReader *reader,
}
void
+_dbus_type_reader_init_from_mark (DBusTypeReader *reader,
+ int byte_order,
+ const DBusString *type_str,
+ const DBusString *value_str,
+ const DBusTypeMark *mark)
+{
+ reader->klass = all_reader_classes[mark->container_type];
+
+ reader_init (reader, byte_order,
+ mark->type_pos_in_value_str ? value_str : type_str,
+ mark->type_pos,
+ value_str, mark->value_pos);
+
+ if (reader->klass->init_from_mark)
+ (* reader->klass->init_from_mark) (reader, mark);
+
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose (" type reader %p init from mark type_pos = %d value_pos = %d remaining sig '%s'\n",
+ reader, reader->type_pos, reader->value_pos,
+ _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
+#endif
+}
+
+void
_dbus_type_reader_init_types_only (DBusTypeReader *reader,
const DBusString *type_str,
int type_pos)
@@ -537,6 +615,45 @@ _dbus_type_reader_init_types_only (DBusTypeReader *reader,
#endif
}
+void
+_dbus_type_reader_init_types_only_from_mark (DBusTypeReader *reader,
+ const DBusString *type_str,
+ const DBusTypeMark *mark)
+{
+ reader->klass = all_reader_classes[mark->container_type];
+ _dbus_assert (reader->klass->types_only);
+ _dbus_assert (!mark->type_pos_in_value_str);
+
+ reader_init (reader, DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
+ type_str, mark->type_pos,
+ NULL, _DBUS_INT_MAX /* crashes if we screw up */);
+
+ if (reader->klass->init_from_mark)
+ (* reader->klass->init_from_mark) (reader, mark);
+
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose (" type reader %p init types only from mark type_pos = %d remaining sig '%s'\n",
+ reader, reader->type_pos,
+ _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
+#endif
+}
+
+void
+_dbus_type_reader_save_mark (DBusTypeReader *reader,
+ DBusTypeMark *mark)
+{
+ mark->type_pos_in_value_str = (reader->type_str == reader->value_str);
+ mark->container_type = reader->klass->id;
+ _dbus_assert (all_reader_classes[reader->klass->id] == reader->klass);
+
+ mark->type_pos = reader->type_pos;
+ mark->value_pos = reader->value_pos;
+
+ /* these are just junk if the reader isn't really an array of course */
+ mark->array_len_offset = reader->array_len_offset;
+ mark->array_start_pos = reader->u.array.start_pos;
+}
+
int
_dbus_type_reader_get_current_type (DBusTypeReader *reader)
{
@@ -565,7 +682,9 @@ _dbus_type_reader_array_is_empty (DBusTypeReader *reader)
_dbus_assert (!reader->klass->types_only);
/* reader is supposed to be at an array child */
- _dbus_verbose ("checking array len at %d\n", reader->value_pos);
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose ("checking array len at %d\n", reader->value_pos);
+#endif
_dbus_demarshal_basic_type (reader->value_str,
DBUS_TYPE_UINT32,
@@ -573,7 +692,9 @@ _dbus_type_reader_array_is_empty (DBusTypeReader *reader)
reader->byte_order,
reader->value_pos,
NULL);
+#if RECURSIVE_MARSHAL_TRACE
_dbus_verbose (" ... array len = %d\n", array_len);
+#endif
return array_len == 0;
}
@@ -661,6 +782,8 @@ _dbus_type_reader_recurse (DBusTypeReader *reader,
_dbus_assert_not_reached ("don't yet handle recursing into this type");
}
+ _dbus_assert (sub->klass == all_reader_classes[sub->klass->id]);
+
(* sub->klass->recurse) (sub, reader);
#if RECURSIVE_MARSHAL_TRACE
@@ -1809,7 +1932,27 @@ node_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed)
{
- return (* node->klass->read_value) (node, block, reader, seed);
+ DBusTypeMark mark;
+ DBusTypeReader restored;
+
+ _dbus_type_reader_save_mark (reader, &mark);
+
+ if (!(* node->klass->read_value) (node, block, reader, seed))
+ return FALSE;
+
+ _dbus_type_reader_init_from_mark (&restored,
+ reader->byte_order, /* a bit of a cheat,
+ * since we didn't bother
+ * to store this in DataBlock
+ */
+ &block->signature,
+ &block->body,
+ &mark);
+
+ if (!(* node->klass->read_value) (node, block, &restored, seed))
+ return FALSE;
+
+ return TRUE;
}
static dbus_bool_t
@@ -2276,6 +2419,8 @@ make_and_run_test_nodes (void)
node_destroy (outer_container);
}
+#if 0
+ /* This one takes a really long time, so comment it out for now */
_dbus_verbose (">>> >>> Each container of each container of each container of each value %d iterations\n",
N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES);
for (i = 0; i < N_CONTAINERS; i++)
@@ -2316,6 +2461,7 @@ make_and_run_test_nodes (void)
}
node_destroy (outer_container);
}
+#endif /* #if 0 expensive test */
_dbus_verbose (">>> >>> Each value,value,value triplet combination as toplevel, in all orders %d iterations\n",
N_VALUES * N_VALUES * N_VALUES);
diff --git a/dbus/dbus-marshal-recursive.h b/dbus/dbus-marshal-recursive.h
index f8384478..59120450 100644
--- a/dbus/dbus-marshal-recursive.h
+++ b/dbus/dbus-marshal-recursive.h
@@ -25,7 +25,8 @@
#define DBUS_MARSHAL_RECURSIVE_H
#include <config.h>
-#include <dbus/dbus-marshal-basic.h> /* this can become protocol.h when we merge */
+#include <dbus/dbus-protocol.h>
+#include <dbus/dbus-marshal-basic.h> /* this can vanish when we merge */
#ifndef PACKAGE
#error "config.h not included here"
@@ -36,6 +37,9 @@
* - delete an array element and re-align the remainder of the array
* (not necessary yet to re-align remainder of entire string,
* though that's probably just as hard/easy)
+ * (really this one is to set a complex-type array element to
+ * a new value, but for dbus-message.c delete-and-reappend would
+ * be good enough)
* - set string, int, etc. values at a memoized position
* (implement generic set of any value? changes only
* value_str not type_str)
@@ -44,10 +48,24 @@
* - validation
*/
+typedef struct DBusTypeMark DBusTypeMark;
typedef struct DBusTypeReader DBusTypeReader;
typedef struct DBusTypeWriter DBusTypeWriter;
typedef struct DBusTypeReaderClass DBusTypeReaderClass;
+/* The mark is a way to compress a TypeReader; it isn't all that
+ * successful though.
+ */
+struct DBusTypeMark
+{
+ dbus_uint32_t type_pos_in_value_str : 1;
+ dbus_uint32_t container_type : 3;
+ dbus_uint32_t array_len_offset : 3; /* bytes back from start_pos that len ends */
+ dbus_uint32_t type_pos : DBUS_MAXIMUM_MESSAGE_LENGTH_BITS;
+ dbus_uint32_t value_pos : DBUS_MAXIMUM_MESSAGE_LENGTH_BITS;
+ dbus_uint32_t array_start_pos : DBUS_MAXIMUM_MESSAGE_LENGTH_BITS;
+};
+
struct DBusTypeReader
{
dbus_uint32_t byte_order : 8;
@@ -55,6 +73,7 @@ struct DBusTypeReader
dbus_uint32_t finished : 1; /* marks we're at end iterator for cases
* where we don't have another way to tell
*/
+ dbus_uint32_t array_len_offset : 3; /* bytes back from start_pos that len ends */
const DBusString *type_str;
int type_pos;
const DBusString *value_str;
@@ -65,8 +84,6 @@ struct DBusTypeReader
{
struct {
int start_pos;
- dbus_uint32_t len;
- int element_type;
} array;
} u;
};
@@ -93,26 +110,37 @@ struct DBusTypeWriter
} u;
};
-void _dbus_type_reader_init (DBusTypeReader *reader,
- int byte_order,
- const DBusString *type_str,
- int type_pos,
- const DBusString *value_str,
- int value_pos);
-void _dbus_type_reader_init_types_only (DBusTypeReader *reader,
- const DBusString *type_str,
- int type_pos);
-int _dbus_type_reader_get_current_type (DBusTypeReader *reader);
-dbus_bool_t _dbus_type_reader_array_is_empty (DBusTypeReader *reader);
-void _dbus_type_reader_read_basic (DBusTypeReader *reader,
- void *value);
-dbus_bool_t _dbus_type_reader_read_array_of_basic (DBusTypeReader *reader,
- int type,
- void **array,
- int *array_len);
-void _dbus_type_reader_recurse (DBusTypeReader *reader,
- DBusTypeReader *subreader);
-dbus_bool_t _dbus_type_reader_next (DBusTypeReader *reader);
+void _dbus_type_reader_init (DBusTypeReader *reader,
+ int byte_order,
+ const DBusString *type_str,
+ int type_pos,
+ const DBusString *value_str,
+ int value_pos);
+void _dbus_type_reader_init_from_mark (DBusTypeReader *reader,
+ int byte_order,
+ const DBusString *type_str,
+ const DBusString *value_str,
+ const DBusTypeMark *mark);
+void _dbus_type_reader_init_types_only (DBusTypeReader *reader,
+ const DBusString *type_str,
+ int type_pos);
+void _dbus_type_reader_init_types_only_from_mark (DBusTypeReader *reader,
+ const DBusString *type_str,
+ const DBusTypeMark *mark);
+void _dbus_type_reader_save_mark (DBusTypeReader *reader,
+ DBusTypeMark *mark);
+int _dbus_type_reader_get_current_type (DBusTypeReader *reader);
+dbus_bool_t _dbus_type_reader_array_is_empty (DBusTypeReader *reader);
+void _dbus_type_reader_read_basic (DBusTypeReader *reader,
+ void *value);
+dbus_bool_t _dbus_type_reader_read_array_of_basic (DBusTypeReader *reader,
+ int type,
+ void **array,
+ int *array_len);
+void _dbus_type_reader_recurse (DBusTypeReader *reader,
+ DBusTypeReader *subreader);
+dbus_bool_t _dbus_type_reader_next (DBusTypeReader *reader);
+
void _dbus_type_writer_init (DBusTypeWriter *writer,
int byte_order,
diff --git a/dbus/dbus-protocol-new.h b/dbus/dbus-protocol-new.h
index 65431eb8..482500f2 100644
--- a/dbus/dbus-protocol-new.h
+++ b/dbus/dbus-protocol-new.h
@@ -89,17 +89,43 @@ extern "C" {
#define DBUS_STRUCT_END_CHAR ((int) ')')
#define DBUS_STRUCT_END_CHAR_AS_STRING ")"
-/* Max length in bytes of a service or interface or member name
- * (not object path, paths are unlimited)
+/* Max length in bytes of a service or interface or member name (not
+ * object path, paths are unlimited). This is limited because lots of
+ * stuff is O(n) in this number, plus it would be obnoxious to type in
+ * a paragraph-long method name so most likely something like that
+ * would be an exploit.
*/
#define DBUS_MAXIMUM_NAME_LENGTH 255
/* This one is 255 so it fits in a byte */
#define DBUS_MAXIMUM_SIGNATURE_LENGTH 255
-/* Max length of a match rule string */
+/* Max length of a match rule string; to keep people from hosing the
+ * daemon with some huge rule
+ */
#define DBUS_MAXIMUM_MATCH_RULE_LENGTH 1024
+/* Max length of a marshaled array in bytes (64M, 2^26) We use signed
+ * int for lengths so must be INT_MAX or less. We need something a
+ * bit smaller than INT_MAX because the array is inside a message with
+ * header info, etc. so an INT_MAX array wouldn't allow the message
+ * overhead. The 64M number is an attempt at a larger number than
+ * we'd reasonably ever use, but small enough that your bus would chew
+ * through it fairly quickly without locking up forever. If you have
+ * data that's likely to be larger than this, you should probably be
+ * sending it in multiple incremental messages anyhow.
+ */
+#define DBUS_MAXIMUM_ARRAY_LENGTH (67108864)
+/* Number of bits you need in an unsigned to store the max array size */
+#define DBUS_MAXIMUM_ARRAY_LENGTH_BITS 26
+
+/* The maximum total message size including header and body; similar
+ * rationale to max array size.
+ */
+#define DBUS_MAXIMUM_MESSAGE_LENGTH (DBUS_MAXIMUM_ARRAY_LENGTH * 2)
+/* Number of bits you need in an unsigned to store the max message size */
+#define DBUS_MAXIMUM_MESSAGE_LENGTH_BITS 27
+
/* Types of message */
#define DBUS_MESSAGE_TYPE_INVALID 0
#define DBUS_MESSAGE_TYPE_METHOD_CALL 1