From 441907e73affff202c75564f4c4b968ff37f094b Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 2 Jan 2005 00:37:24 +0000 Subject: add DBusTypeMark --- dbus/dbus-marshal-basic.h | 4 + dbus/dbus-marshal-recursive.c | 230 ++++++++++++++++++++++++++++++++++-------- dbus/dbus-marshal-recursive.h | 74 +++++++++----- dbus/dbus-protocol-new.h | 32 +++++- 4 files changed, 272 insertions(+), 68 deletions(-) (limited to 'dbus') 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 @@ -520,6 +574,30 @@ _dbus_type_reader_init (DBusTypeReader *reader, #endif } +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, @@ -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 -#include /* this can become protocol.h when we merge */ +#include +#include /* 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 -- cgit