From 617e73f7631e605fc9ebf6a67042a1f451b97850 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 19 Dec 2004 16:23:09 +0000 Subject: [PATCH] 2004-12-19 Havoc Pennington * dbus/dbus-string.c (_dbus_string_insert_4_aligned) (_dbus_string_insert_8_aligned): new functions * dbus/dbus-string.c (_dbus_string_alloc_space): new function --- ChangeLog | 7 + dbus/dbus-marshal-basic.c | 203 +++++++++++-------- dbus/dbus-marshal-basic.h | 71 +++++-- dbus/dbus-marshal-recursive.c | 362 +++++++++++++++++++++++++++------- dbus/dbus-marshal-recursive.h | 44 ++--- dbus/dbus-protocol-new.h | 3 +- dbus/dbus-string.c | 197 ++++++++++++++---- dbus/dbus-string.h | 11 ++ 8 files changed, 664 insertions(+), 234 deletions(-) diff --git a/ChangeLog b/ChangeLog index dfe5c6cd..b2f2c74c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2004-12-19 Havoc Pennington + + * dbus/dbus-string.c (_dbus_string_insert_4_aligned) + (_dbus_string_insert_8_aligned): new functions + + * dbus/dbus-string.c (_dbus_string_alloc_space): new function + 2004-12-18 Havoc Pennington * dbus/dbus-string.c (_dbus_string_validate_ascii): use ISASCII diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c index 76477279..d325d5f0 100644 --- a/dbus/dbus-marshal-basic.c +++ b/dbus/dbus-marshal-basic.c @@ -22,11 +22,12 @@ * */ -#include "dbus-marshal-basic.h" #include "dbus-internals.h" #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1 #include "dbus-string-private.h" +#include "dbus-marshal-basic.h" + #include /** @@ -85,7 +86,7 @@ typedef union { #ifdef DBUS_HAVE_INT64 dbus_int64_t s; /**< 64-bit integer */ - dbus_uint64_t u; /**< 64-bit unsinged integer */ + dbus_uint64_t u; /**< 64-bit unsigned integer */ #endif double d; /**< double */ } DBusOctets8; @@ -462,6 +463,7 @@ _dbus_marshal_set_object_path (DBusString *str, static dbus_bool_t marshal_4_octets (DBusString *str, + int insert_at, int byte_order, dbus_uint32_t value) { @@ -470,12 +472,13 @@ marshal_4_octets (DBusString *str, if (byte_order != DBUS_COMPILER_BYTE_ORDER) value = DBUS_UINT32_SWAP_LE_BE (value); - return _dbus_string_append_4_aligned (str, + return _dbus_string_insert_4_aligned (str, insert_at, (const unsigned char *)&value); } static dbus_bool_t marshal_8_octets (DBusString *str, + int insert_at, int byte_order, DBusOctets8 value) { @@ -484,7 +487,7 @@ marshal_8_octets (DBusString *str, if (byte_order != DBUS_COMPILER_BYTE_ORDER) pack_8_octets (value, byte_order, (unsigned char*) &value); /* pack into self, swapping as we go */ - return _dbus_string_append_8_aligned (str, + return _dbus_string_insert_8_aligned (str, insert_at, (const unsigned char *)&value); } @@ -503,7 +506,8 @@ _dbus_marshal_double (DBusString *str, { DBusOctets8 r; r.d = value; - return marshal_8_octets (str, byte_order, r); + return marshal_8_octets (str, _dbus_string_get_length (str), + byte_order, r); } /** @@ -519,7 +523,8 @@ _dbus_marshal_int32 (DBusString *str, int byte_order, dbus_int32_t value) { - return marshal_4_octets (str, byte_order, (dbus_uint32_t) value); + return marshal_4_octets (str, _dbus_string_get_length (str), + byte_order, (dbus_uint32_t) value); } /** @@ -531,11 +536,12 @@ _dbus_marshal_int32 (DBusString *str, * @returns #TRUE on success */ dbus_bool_t -_dbus_marshal_uint32 (DBusString *str, - int byte_order, - dbus_uint32_t value) +_dbus_marshal_uint32 (DBusString *str, + int byte_order, + dbus_uint32_t value) { - return marshal_4_octets (str, byte_order, value); + return marshal_4_octets (str, _dbus_string_get_length (str), + byte_order, value); } @@ -555,7 +561,8 @@ _dbus_marshal_int64 (DBusString *str, { DBusOctets8 r; r.s = value; - return marshal_8_octets (str, byte_order, r); + return marshal_8_octets (str, _dbus_string_get_length (str), + byte_order, r); } /** @@ -573,7 +580,8 @@ _dbus_marshal_uint64 (DBusString *str, { DBusOctets8 r; r.u = value; - return marshal_8_octets (str, byte_order, r); + return marshal_8_octets (str, _dbus_string_get_length (str), + byte_order, r); } #endif /* DBUS_HAVE_INT64 */ @@ -930,7 +938,7 @@ _dbus_marshal_string_array (DBusString *str, * @param path_len length of the path * @returns #TRUE on success */ -dbus_bool_t +static dbus_bool_t _dbus_marshal_object_path (DBusString *str, int byte_order, const char **path, @@ -1160,7 +1168,15 @@ _dbus_demarshal_basic_type (const DBusString *str, #endif *pos += 8; break; + case DBUS_TYPE_STRING: + _dbus_assert_not_reached ("FIXME string is a basic type"); + break; + case DBUS_TYPE_OBJECT_PATH: + _dbus_assert_not_reached ("FIXME object path is a basic type"); + break; default: + _dbus_verbose ("type %s not a basic type\n", + _dbus_type_to_string (type)); _dbus_assert_not_reached ("not a basic type"); break; } @@ -1746,6 +1762,74 @@ _dbus_demarshal_object_path (const DBusString *str, return TRUE; } +/** + * Skips over a basic type, reporting the following position. + * + * @param str the string containing the data + * @param type type of value to demarshal + * @param byte_order the byte order + * @param pos pointer to position in the string, + * updated on return to new position + **/ +void +_dbus_marshal_skip_basic_type (const DBusString *str, + int type, + int byte_order, + int *pos) +{ + switch (type) + { + case DBUS_TYPE_BYTE: + case DBUS_TYPE_BOOLEAN: + (*pos)++; + break; + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + *pos = _DBUS_ALIGN_VALUE (*pos, 4); + *pos += 4; + break; +#ifdef DBUS_HAVE_INT64 + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: +#endif /* DBUS_HAVE_INT64 */ + case DBUS_TYPE_DOUBLE: + *pos = _DBUS_ALIGN_VALUE (*pos, 8); + *pos += 8; + break; + case DBUS_TYPE_STRING: + _dbus_assert_not_reached ("FIXME string is a basic type"); + break; + case DBUS_TYPE_OBJECT_PATH: + _dbus_assert_not_reached ("FIXME object path is a basic type"); + break; + default: + _dbus_verbose ("type %s not a basic type\n", + _dbus_type_to_string (type)); + _dbus_assert_not_reached ("not a basic type"); + break; + } +} + +/** + * Skips an array, returning the next position. + * + * @param str the string containing the data + * @param byte_order the byte order + * @param pos pointer to position in the string, + * updated on return to new position + */ +void +_dbus_marshal_skip_array (const DBusString *str, + int byte_order, + int *pos) +{ + int len; + + len = _dbus_demarshal_uint32 (str, byte_order, *pos, pos); + + *pos += len; +} + /** * Returns the position right after the end of an argument. PERFORMS * NO VALIDATION WHATSOEVER. The message must have been previously @@ -1775,10 +1859,6 @@ _dbus_marshal_get_arg_end_pos (const DBusString *str, return FALSE; break; - case DBUS_TYPE_NIL: - *end_pos = pos; - break; - case DBUS_TYPE_BYTE: *end_pos = pos + 1; break; @@ -1810,22 +1890,6 @@ _dbus_marshal_get_arg_end_pos (const DBusString *str, *end_pos = pos + len + 1; } break; - - case DBUS_TYPE_CUSTOM: - { - int len; - - /* Demarshal the string length */ - len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); - - pos += len + 1; - - /* Demarshal the data length */ - len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos); - - *end_pos = pos + len; - } - break; case DBUS_TYPE_ARRAY: { @@ -2002,12 +2066,8 @@ validate_array_data (const DBusString *str, return FALSE; break; - case DBUS_TYPE_NIL: - break; - case DBUS_TYPE_OBJECT_PATH: case DBUS_TYPE_STRING: - case DBUS_TYPE_CUSTOM: case DBUS_TYPE_ARRAY: case DBUS_TYPE_DICT: /* This clean recursion to validate_arg is what we @@ -2127,10 +2187,6 @@ _dbus_marshal_validate_arg (const DBusString *str, return FALSE; break; - case DBUS_TYPE_NIL: - *end_pos = pos; - break; - case DBUS_TYPE_BYTE: if (1 > _dbus_string_get_length (str) - pos) { @@ -2220,29 +2276,6 @@ _dbus_marshal_validate_arg (const DBusString *str, } } break; - - case DBUS_TYPE_CUSTOM: - { - int len; - - /* Demarshal the string length, which does NOT include - * nul termination - */ - len = demarshal_and_validate_len (str, byte_order, pos, &pos); - if (len < 0) - return FALSE; - - if (!validate_string (str, pos, len, &pos)) - return FALSE; - - /* Validate data */ - len = demarshal_and_validate_len (str, byte_order, pos, &pos); - if (len < 0) - return FALSE; - - *end_pos = pos + len; - } - break; case DBUS_TYPE_ARRAY: { @@ -2261,16 +2294,6 @@ _dbus_marshal_validate_arg (const DBusString *str, _dbus_verbose ("invalid array type\n"); return FALSE; } - - /* NIL values take up no space, so you couldn't iterate over an array of them. - * array of nil seems useless anyway; the useful thing might be array of - * (nil OR string) but we have no framework for that. - */ - if (array_type == DBUS_TYPE_NIL) - { - _dbus_verbose ("array of NIL is not allowed\n"); - return FALSE; - } } while (array_type == DBUS_TYPE_ARRAY); } @@ -2397,7 +2420,6 @@ _dbus_type_is_valid (int typecode) { switch (typecode) { - case DBUS_TYPE_NIL: case DBUS_TYPE_BYTE: case DBUS_TYPE_BOOLEAN: case DBUS_TYPE_INT32: @@ -2406,7 +2428,6 @@ _dbus_type_is_valid (int typecode) case DBUS_TYPE_UINT64: case DBUS_TYPE_DOUBLE: case DBUS_TYPE_STRING: - case DBUS_TYPE_CUSTOM: case DBUS_TYPE_ARRAY: case DBUS_TYPE_DICT: case DBUS_TYPE_OBJECT_PATH: @@ -2457,7 +2478,7 @@ _dbus_verbose_bytes (const unsigned char *data, if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i]) { _dbus_verbose ("%4d\t%p: ", - i, &data[i]); + i, &data[i]); } if (data[i] >= 32 && @@ -2465,7 +2486,7 @@ _dbus_verbose_bytes (const unsigned char *data, _dbus_verbose (" '%c' ", data[i]); else _dbus_verbose ("0x%s%x ", - data[i] <= 0xf ? "0" : "", data[i]); + data[i] <= 0xf ? "0" : "", data[i]); ++i; @@ -2532,6 +2553,7 @@ _dbus_verbose_bytes_of_string (const DBusString *str, * Marshals a basic type * * @param str string to marshal to + * @param insert_at where to insert the value * @param type type of value * @param value pointer to value * @param byte_order byte order @@ -2539,8 +2561,9 @@ _dbus_verbose_bytes_of_string (const DBusString *str, **/ dbus_bool_t _dbus_marshal_basic_type (DBusString *str, + int insert_at, char type, - void *value, + const void *value, int byte_order) { dbus_bool_t retval; @@ -2549,20 +2572,28 @@ _dbus_marshal_basic_type (DBusString *str, { case DBUS_TYPE_BYTE: case DBUS_TYPE_BOOLEAN: - retval = _dbus_string_append_byte (str, *(unsigned char *)value); + retval = _dbus_string_insert_byte (str, insert_at, *(const unsigned char *)value); break; case DBUS_TYPE_INT32: case DBUS_TYPE_UINT32: - return marshal_4_octets (str, byte_order, *(dbus_uint32_t *)value); + return marshal_4_octets (str, insert_at, byte_order, *(const dbus_uint32_t *)value); break; #ifdef DBUS_HAVE_INT64 case DBUS_TYPE_INT64: - case DBUS_TYPE_UINT64: - retval = _dbus_marshal_uint64 (str, byte_order, *(dbus_uint64_t *)value); + case DBUS_TYPE_UINT64: + { + DBusOctets8 r; + r.u = *(const dbus_uint64_t *)value; + retval = marshal_8_octets (str, insert_at, byte_order, r); + } break; #endif /* DBUS_HAVE_INT64 */ case DBUS_TYPE_DOUBLE: - retval = _dbus_marshal_double (str, byte_order, *(double *)value); + { + DBusOctets8 r; + r.d = *(const double *)value; + retval = marshal_8_octets (str, insert_at, byte_order, r); + } break; default: _dbus_assert_not_reached ("not a basic type"); @@ -2576,6 +2607,7 @@ _dbus_marshal_basic_type (DBusString *str, * Marshals a basic type array * * @param str string to marshal to + * @param insert_at where to insert the value * @param element_type type of array elements * @param value pointer to value * @param len length of value data in elements @@ -2584,11 +2616,14 @@ _dbus_marshal_basic_type (DBusString *str, **/ dbus_bool_t _dbus_marshal_basic_type_array (DBusString *str, + int insert_at, char element_type, const void *value, int len, int byte_order) { + /* FIXME use the insert_at arg */ + switch (element_type) { case DBUS_TYPE_BOOLEAN: diff --git a/dbus/dbus-marshal-basic.h b/dbus/dbus-marshal-basic.h index 25db7cc5..e8c0b3fb 100644 --- a/dbus/dbus-marshal-basic.h +++ b/dbus/dbus-marshal-basic.h @@ -37,6 +37,8 @@ /****************************************************** Remove later */ #undef DBUS_TYPE_INVALID +#undef DBUS_TYPE_NIL +#undef DBUS_TYPE_CUSTOM #undef DBUS_TYPE_BYTE #undef DBUS_TYPE_INT32 #undef DBUS_TYPE_UINT32 @@ -83,7 +85,43 @@ /* characters other than typecodes that appear in type signatures */ #define DBUS_STRUCT_BEGIN_CHAR ((int) '(') #define DBUS_STRUCT_END_CHAR ((int) ')') -#define DBUS_NAME_DELIMITER_CHAR ((int) '\'') + +static const char * +_hack_dbus_type_to_string (int type) +{ + switch (type) + { + case DBUS_TYPE_INVALID: + return "invalid"; + case DBUS_TYPE_BOOLEAN: + return "boolean"; + case DBUS_TYPE_INT32: + return "int32"; + case DBUS_TYPE_UINT32: + return "uint32"; + case DBUS_TYPE_DOUBLE: + return "double"; + case DBUS_TYPE_STRING: + return "string"; + case DBUS_TYPE_STRUCT: + return "struct"; + case DBUS_TYPE_ARRAY: + return "array"; + case DBUS_TYPE_DICT: + return "dict"; + case DBUS_TYPE_VARIANT: + return "variant"; + case DBUS_STRUCT_BEGIN_CHAR: + return "begin_struct"; + case DBUS_STRUCT_END_CHAR: + return "end_struct"; + default: + return "unknown"; + } +} + +#define _dbus_type_to_string(t) _hack_dbus_type_to_string(t) + /****************************************************** Remove later */ #ifdef WORDS_BIGENDIAN @@ -222,6 +260,7 @@ dbus_bool_t _dbus_marshal_int32 (DBusString *str, dbus_bool_t _dbus_marshal_uint32 (DBusString *str, int byte_order, dbus_uint32_t value); + #ifdef DBUS_HAVE_INT64 dbus_bool_t _dbus_marshal_int64 (DBusString *str, int byte_order, @@ -233,6 +272,7 @@ dbus_bool_t _dbus_marshal_uint64 (DBusString *str, dbus_bool_t _dbus_marshal_double (DBusString *str, int byte_order, double value); + dbus_bool_t _dbus_marshal_string (DBusString *str, int byte_order, const char *value); @@ -240,10 +280,18 @@ dbus_bool_t _dbus_marshal_string_len (DBusString *str, int byte_order, const char *value, int len); + dbus_bool_t _dbus_marshal_basic_type (DBusString *str, + int insert_at, char type, - void *value, + const void *value, int byte_order); +dbus_bool_t _dbus_marshal_basic_type_array (DBusString *str, + int insert_at, + char element_type, + const void *value, + int len, + int byte_order); dbus_bool_t _dbus_marshal_byte_array (DBusString *str, int byte_order, const unsigned char *value, @@ -270,21 +318,10 @@ dbus_bool_t _dbus_marshal_double_array (DBusString *str, int byte_order, const double *value, int len); -dbus_bool_t _dbus_marshal_basic_type_array (DBusString *str, - char element_type, - const void *value, - int len, - int byte_order); - dbus_bool_t _dbus_marshal_string_array (DBusString *str, int byte_order, const char **value, int len); -dbus_bool_t _dbus_marshal_object_path (DBusString *str, - int byte_order, - const char **path, - int path_len); - double _dbus_demarshal_double (const DBusString *str, int byte_order, int pos, @@ -378,6 +415,14 @@ dbus_bool_t _dbus_demarshal_object_path (const DBusString *str, char ***path, int *path_len); +void _dbus_marshal_skip_basic_type (const DBusString *str, + int type, + int byte_order, + int *pos); +void _dbus_marshal_skip_array (const DBusString *str, + int byte_order, + int *pos); + dbus_bool_t _dbus_marshal_get_arg_end_pos (const DBusString *str, int byte_order, int type, diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c index eb85a2c4..1962e629 100644 --- a/dbus/dbus-marshal-recursive.c +++ b/dbus/dbus-marshal-recursive.c @@ -37,76 +37,197 @@ _dbus_type_reader_init (DBusTypeReader *reader, const DBusString *value_str, int value_pos) { - + reader->byte_order = byte_order; + reader->type_str = type_str; + reader->type_pos = type_pos; + reader->value_str = value_str; + reader->value_pos = value_pos; + _dbus_verbose ("type reader %p init 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)); } int -_dbus_type_reader_get_value_end (DBusTypeReader *reader) +_dbus_type_reader_get_current_type (DBusTypeReader *reader) { + int t; + t = _dbus_string_get_byte (reader->type_str, + reader->type_pos); -} - -int -_dbus_type_reader_get_type_end (DBusTypeReader *reader) -{ + if (t == DBUS_STRUCT_BEGIN_CHAR) + t = DBUS_TYPE_STRUCT; + /* this should never be a stopping place */ + _dbus_assert (t != DBUS_STRUCT_END_CHAR); +#if 0 + _dbus_verbose ("type reader %p current type_pos = %d type = %s\n", + reader, reader->type_pos, + _dbus_type_to_string (t)); +#endif + + return t; } int -_dbus_type_reader_get_current_type (DBusTypeReader *reader) +_dbus_type_reader_get_array_type (DBusTypeReader *reader) { + int t; + t = _dbus_type_reader_get_current_type (reader); -} - -int -_dbus_type_reader_get_array_type (DBusTypeReader *reader) -{ - + if (t != DBUS_TYPE_ARRAY) + return DBUS_TYPE_INVALID; + t = _dbus_string_get_byte (reader->type_str, + reader->type_pos + 1); + + return t; } void _dbus_type_reader_read_basic (DBusTypeReader *reader, void *value) { + int t; + int next; + t = _dbus_type_reader_get_current_type (reader); + next = reader->value_pos; + _dbus_demarshal_basic_type (reader->value_str, + t, value, + reader->byte_order, + &next); + + _dbus_verbose ("type reader %p read basic type_pos = %d value_pos = %d next = %d remaining sig '%s'\n", + reader, reader->type_pos, reader->value_pos, next, + _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0)); + + _dbus_verbose_bytes_of_string (reader->value_str, + reader->value_pos, + MIN (16, + _dbus_string_get_length (reader->value_str) - reader->value_pos)); } dbus_bool_t -_dbus_type_reader_read_array (DBusTypeReader *reader, - int type, - void **array, - int *array_len) +_dbus_type_reader_read_array_of_basic (DBusTypeReader *reader, + int type, + void **array, + int *array_len) { - - + + } +/** + * Initialize a new reader pointing to the first type and + * corresponding value that's a child of the current container. It's + * an error to call this if the current type is a non-container. + * + * @param reader the reader + * @param sub a reader to init pointing to the first child + */ void -_dbus_type_reader_recurse (DBusTypeReader *reader) +_dbus_type_reader_recurse (DBusTypeReader *reader, + DBusTypeReader *sub) { + int t; + t = _dbus_string_get_byte (reader->type_str, reader->type_pos); + + /* point subreader at the same place as reader */ + _dbus_type_reader_init (sub, + reader->byte_order, + reader->type_str, + reader->type_pos, + reader->value_str, + reader->value_pos); -} - -void -_dbus_type_reader_unrecurse (DBusTypeReader *reader) -{ + _dbus_assert (t == DBUS_STRUCT_BEGIN_CHAR); /* only this works right now */ + + sub->type_pos += 1; + /* no value_pos increment since the struct itself doesn't take up value space */ + _dbus_verbose ("type reader %p recursed type_pos = %d value_pos = %d remaining sig '%s'\n", + sub, sub->type_pos, sub->value_pos, + _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0)); } +/** + * Skip to the next value on this "level". e.g. the next field in a + * struct, the next value in an array, the next key or value in a + * dict. Returns FALSE at the end of the current container. + * + * @param reader the reader + * @returns FALSE if nothing more to read at or below this level + */ dbus_bool_t -_dbus_type_reader_next (DBusTypeReader *reader) +_dbus_type_reader_next (DBusTypeReader *reader) { + int t; + /* FIXME handled calling next when there's no next */ + + t = _dbus_string_get_byte (reader->type_str, reader->type_pos); + + _dbus_verbose ("type reader %p next() { 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)); + + switch (t) + { + case DBUS_STRUCT_BEGIN_CHAR: + /* Scan forward over the entire container contents */ + { + DBusTypeReader sub; + + /* Recurse into the struct */ + _dbus_type_reader_recurse (reader, &sub); + + /* Skip everything in this subreader */ + while (_dbus_type_reader_next (&sub)) + { + /* nothing */; + } + + /* Now we are at the end of this container */ + reader->type_pos = sub.type_pos; + reader->value_pos = sub.value_pos; + } + break; + + default: + /* FIXME for array etc. this is more complicated */ + _dbus_marshal_skip_basic_type (reader->value_str, + t, reader->byte_order, + &reader->value_pos); + reader->type_pos += 1; + break; + } + _dbus_verbose ("type reader %p } 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)); + /* FIXME this is wrong; we need to return FALSE when we finish the + * container we've recursed into; even if the signature continues. + */ + + t = _dbus_string_get_byte (reader->type_str, reader->type_pos); + + if (t == DBUS_STRUCT_END_CHAR) + { + reader->type_pos += 1; + return FALSE; + } + if (t == DBUS_TYPE_INVALID) + return FALSE; + + return TRUE; } void @@ -117,8 +238,12 @@ _dbus_type_writer_init (DBusTypeWriter *writer, DBusString *value_str, int value_pos) { - - + writer->byte_order = byte_order; + writer->type_str = type_str; + writer->type_pos = type_pos; + writer->value_str = value_str; + writer->value_pos = value_pos; + writer->container_type = DBUS_TYPE_INVALID; } dbus_bool_t @@ -126,8 +251,38 @@ _dbus_type_writer_write_basic (DBusTypeWriter *writer, int type, const void *value) { + dbus_bool_t retval; + int old_value_len; + old_value_len = _dbus_string_get_length (writer->value_str); + + /* First ensure that our type realloc will succeed */ + if (!_dbus_string_alloc_space (writer->type_str, 1)) + return FALSE; + retval = FALSE; + + if (!_dbus_marshal_basic_type (writer->value_str, + writer->value_pos, + type, + value, + writer->byte_order)) + goto out; + + writer->value_pos += _dbus_string_get_length (writer->value_str) - old_value_len; + + /* Now insert the type */ + if (!_dbus_string_insert_byte (writer->type_str, + writer->type_pos, + type)) + _dbus_assert_not_reached ("failed to insert byte after prealloc"); + + writer->type_pos += 1; + + retval = TRUE; + + out: + return retval; } dbus_bool_t @@ -142,17 +297,57 @@ _dbus_type_writer_write_array (DBusTypeWriter *writer, dbus_bool_t _dbus_type_writer_recurse (DBusTypeWriter *writer, - int container_type) -{ - - + int container_type, + DBusTypeWriter *sub) +{ + _dbus_type_writer_init (sub, + writer->byte_order, + writer->type_str, + writer->type_pos, + writer->value_str, + writer->value_pos); + sub->container_type = container_type; + + switch (container_type) + { + case DBUS_TYPE_STRUCT: + { + if (!_dbus_string_insert_byte (sub->type_str, + sub->type_pos, + DBUS_STRUCT_BEGIN_CHAR)) + return FALSE; + + sub->type_pos += 1; + } + break; + default: + _dbus_assert_not_reached ("container_type unhandled"); + break; + } + + return TRUE; } dbus_bool_t -_dbus_type_writer_unrecurse (DBusTypeWriter *writer) +_dbus_type_writer_unrecurse (DBusTypeWriter *writer, + DBusTypeWriter *sub) { + _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */ + if (sub->container_type == DBUS_TYPE_STRUCT) + { + if (!_dbus_string_insert_byte (sub->type_str, + sub->type_pos, + DBUS_STRUCT_END_CHAR)) + return FALSE; + sub->type_pos += 1; + } + /* Jump the parent writer to the new location */ + writer->type_pos = sub->type_pos; + writer->value_pos = sub->value_pos; + + return TRUE; } /** @} */ /* end of DBusMarshal group */ @@ -266,6 +461,12 @@ check_expected_type (DBusTypeReader *reader, _dbus_warn ("Read type %s while expecting %s\n", _dbus_type_to_string (t), _dbus_type_to_string (expected)); + + _dbus_verbose_bytes_of_string (reader->type_str, 0, + _dbus_string_get_length (reader->type_str)); + _dbus_verbose_bytes_of_string (reader->value_str, 0, + _dbus_string_get_length (reader->value_str)); + exit (1); } } @@ -292,15 +493,17 @@ write_struct_with_int32s (DataBlock *block, { dbus_int32_t v; DataBlockState saved; + DBusTypeWriter sub; data_block_save (block, &saved); if (!_dbus_type_writer_recurse (writer, - DBUS_TYPE_STRUCT)) + DBUS_TYPE_STRUCT, + &sub)) return FALSE; v = SAMPLE_INT32; - if (!_dbus_type_writer_write_basic (writer, + if (!_dbus_type_writer_write_basic (&sub, DBUS_TYPE_INT32, &v)) { @@ -309,7 +512,7 @@ write_struct_with_int32s (DataBlock *block, } v = SAMPLE_INT32_ALTERNATE; - if (!_dbus_type_writer_write_basic (writer, + if (!_dbus_type_writer_write_basic (&sub, DBUS_TYPE_INT32, &v)) { @@ -317,7 +520,7 @@ write_struct_with_int32s (DataBlock *block, return FALSE; } - if (!_dbus_type_writer_unrecurse (writer)) + if (!_dbus_type_writer_unrecurse (writer, &sub)) { data_block_restore (block, &saved); return FALSE; @@ -331,27 +534,26 @@ read_struct_with_int32s (DataBlock *block, DBusTypeReader *reader) { dbus_int32_t v; + DBusTypeReader sub; check_expected_type (reader, DBUS_TYPE_STRUCT); - _dbus_type_reader_recurse (reader); + _dbus_type_reader_recurse (reader, &sub); - check_expected_type (reader, DBUS_TYPE_INT32); + check_expected_type (&sub, DBUS_TYPE_INT32); - _dbus_type_reader_read_basic (reader, + _dbus_type_reader_read_basic (&sub, (dbus_int32_t*) &v); _dbus_assert (v == SAMPLE_INT32); - _dbus_type_reader_next (reader); - check_expected_type (reader, DBUS_TYPE_INT32); + _dbus_type_reader_next (&sub); + check_expected_type (&sub, DBUS_TYPE_INT32); - _dbus_type_reader_read_basic (reader, + _dbus_type_reader_read_basic (&sub, (dbus_int32_t*) &v); _dbus_assert (v == SAMPLE_INT32_ALTERNATE); - - _dbus_type_reader_unrecurse (reader); return TRUE; } @@ -361,30 +563,32 @@ write_struct_of_structs (DataBlock *block, DBusTypeWriter *writer) { DataBlockState saved; + DBusTypeWriter sub; data_block_save (block, &saved); if (!_dbus_type_writer_recurse (writer, - DBUS_TYPE_STRUCT)) + DBUS_TYPE_STRUCT, + &sub)) return FALSE; - if (!write_struct_with_int32s (block, writer)) + if (!write_struct_with_int32s (block, &sub)) { data_block_restore (block, &saved); return FALSE; } - if (!write_struct_with_int32s (block, writer)) + if (!write_struct_with_int32s (block, &sub)) { data_block_restore (block, &saved); return FALSE; } - if (!write_struct_with_int32s (block, writer)) + if (!write_struct_with_int32s (block, &sub)) { data_block_restore (block, &saved); return FALSE; } - if (!_dbus_type_writer_unrecurse (writer)) + if (!_dbus_type_writer_unrecurse (writer, &sub)) { data_block_restore (block, &saved); return FALSE; @@ -397,20 +601,20 @@ static dbus_bool_t read_struct_of_structs (DataBlock *block, DBusTypeReader *reader) { + DBusTypeReader sub; + check_expected_type (reader, DBUS_TYPE_STRUCT); - _dbus_type_reader_recurse (reader); + _dbus_type_reader_recurse (reader, &sub); - if (!read_struct_with_int32s (block, reader)) + if (!read_struct_with_int32s (block, &sub)) return FALSE; - _dbus_type_reader_next (reader); - if (!read_struct_with_int32s (block, reader)) + _dbus_type_reader_next (&sub); + if (!read_struct_with_int32s (block, &sub)) return FALSE; - _dbus_type_reader_next (reader); - if (!read_struct_with_int32s (block, reader)) + _dbus_type_reader_next (&sub); + if (!read_struct_with_int32s (block, &sub)) return FALSE; - - _dbus_type_reader_unrecurse (reader); return TRUE; } @@ -420,25 +624,27 @@ write_struct_of_structs_of_structs (DataBlock *block, DBusTypeWriter *writer) { DataBlockState saved; + DBusTypeWriter sub; data_block_save (block, &saved); if (!_dbus_type_writer_recurse (writer, - DBUS_TYPE_STRUCT)) + DBUS_TYPE_STRUCT, + &sub)) return FALSE; - if (!write_struct_of_structs (block, writer)) + if (!write_struct_of_structs (block, &sub)) { data_block_restore (block, &saved); return FALSE; } - if (!write_struct_of_structs (block, writer)) + if (!write_struct_of_structs (block, &sub)) { data_block_restore (block, &saved); return FALSE; } - if (!_dbus_type_writer_unrecurse (writer)) + if (!_dbus_type_writer_unrecurse (writer, &sub)) { data_block_restore (block, &saved); return FALSE; @@ -451,17 +657,17 @@ static dbus_bool_t read_struct_of_structs_of_structs (DataBlock *block, DBusTypeReader *reader) { + DBusTypeReader sub; + check_expected_type (reader, DBUS_TYPE_STRUCT); - _dbus_type_reader_recurse (reader); + _dbus_type_reader_recurse (reader, &sub); - if (!read_struct_of_structs (block, reader)) + if (!read_struct_of_structs (block, &sub)) return FALSE; - _dbus_type_reader_next (reader); - if (!read_struct_of_structs (block, reader)) + _dbus_type_reader_next (&sub); + if (!read_struct_of_structs (block, &sub)) return FALSE; - - _dbus_type_reader_unrecurse (reader); return TRUE; } @@ -483,16 +689,21 @@ typedef dbus_bool_t (* ReadItemFunc) (DataBlock *block, typedef struct { + const char *desc; WhichItem which; WriteItemFunc write_item_func; ReadItemFunc read_item_func; } CheckMarshalItem; static CheckMarshalItem items[] = { - { ITEM_INT32, write_int32, read_int32 }, - { ITEM_STRUCT_WITH_INT32S, write_struct_with_int32s, read_struct_with_int32s }, - { ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs }, - { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, + { "int32", + ITEM_INT32, write_int32, read_int32 }, + { "struct with two int32", + ITEM_STRUCT_WITH_INT32S, write_struct_with_int32s, read_struct_with_int32s }, + { "struct with three structs of two int32", + ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs }, + { "struct of two structs of three structs of two int32", + ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, write_struct_of_structs_of_structs, read_struct_of_structs_of_structs } }; @@ -559,6 +770,9 @@ perform_one_run (DataBlock *block, while (run->items[i] != ITEM_INVALID) { CheckMarshalItem *item = &items[run->items[i]]; + + _dbus_verbose ("writing %s\n", item->desc); + if (!(* item->write_item_func) (block, &writer)) goto out; ++i; @@ -568,6 +782,8 @@ perform_one_run (DataBlock *block, while (run->items[i] != ITEM_INVALID) { CheckMarshalItem *item = &items[run->items[i]]; + + _dbus_verbose ("reading %s\n", item->desc); if (!(* item->read_item_func) (block, &reader)) goto out; diff --git a/dbus/dbus-marshal-recursive.h b/dbus/dbus-marshal-recursive.h index 19960ec8..ed70a827 100644 --- a/dbus/dbus-marshal-recursive.h +++ b/dbus/dbus-marshal-recursive.h @@ -67,30 +67,28 @@ struct DBusTypeWriter int type_pos; DBusString *value_str; int value_pos; + int container_type; }; typedef struct DBusTypeWriter DBusTypeWriter; -void _dbus_type_reader_init (DBusTypeReader *reader, - int byte_order, - const DBusString *type_str, - int type_pos, - const DBusString *value_str, - int value_pos); -int _dbus_type_reader_get_value_end (DBusTypeReader *reader); -int _dbus_type_reader_get_type_end (DBusTypeReader *reader); -int _dbus_type_reader_get_current_type (DBusTypeReader *reader); -int _dbus_type_reader_get_array_type (DBusTypeReader *reader); -void _dbus_type_reader_read_basic (DBusTypeReader *reader, - void *value); -dbus_bool_t _dbus_type_reader_read_array (DBusTypeReader *reader, - int type, - void **array, - int *array_len); -void _dbus_type_reader_recurse (DBusTypeReader *reader); -void _dbus_type_reader_unrecurse (DBusTypeReader *reader); -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); +int _dbus_type_reader_get_current_type (DBusTypeReader *reader); +int _dbus_type_reader_get_array_type (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, @@ -106,7 +104,9 @@ dbus_bool_t _dbus_type_writer_write_array (DBusTypeWriter *writer, const void *array, int array_len); dbus_bool_t _dbus_type_writer_recurse (DBusTypeWriter *writer, - int container_type); -dbus_bool_t _dbus_type_writer_unrecurse (DBusTypeWriter *writer); + int container_type, + DBusTypeWriter *sub); +dbus_bool_t _dbus_type_writer_unrecurse (DBusTypeWriter *writer, + DBusTypeWriter *sub); #endif /* DBUS_MARSHAL_RECURSIVE_H */ diff --git a/dbus/dbus-protocol-new.h b/dbus/dbus-protocol-new.h index b029f0fb..9d8c4b6f 100644 --- a/dbus/dbus-protocol-new.h +++ b/dbus/dbus-protocol-new.h @@ -58,7 +58,7 @@ extern "C" { /* Compound types */ #define DBUS_TYPE_ARRAY ((int) 'a') -#define DBUS_TYPE_DICT ((int) 'm') +#define DBUS_TYPE_DICT ((int) 'm') /* not parameterized; always map */ #define DBUS_TYPE_VARIANT ((int) 'v') /* STRUCT is sort of special since its code can't appear in a type string, @@ -72,7 +72,6 @@ extern "C" { /* characters other than typecodes that appear in type signatures */ #define DBUS_STRUCT_BEGIN_CHAR ((int) '(') #define DBUS_STRUCT_END_CHAR ((int) ')') -#define DBUS_NAME_DELIMITER_CHAR ((int) '\'') /* Max length in bytes of a service or interface or member name */ #define DBUS_MAXIMUM_NAME_LENGTH 256 diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c index 1188c6cb..b4e626b5 100644 --- a/dbus/dbus-string.c +++ b/dbus/dbus-string.c @@ -611,6 +611,31 @@ _dbus_string_insert_bytes (DBusString *str, return TRUE; } +/** + * Inserts a single byte at the given position. + * + * @param str the string + * @param i the position + * @param byte the value to insert + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_string_insert_byte (DBusString *str, + int i, + unsigned char byte) +{ + DBUS_STRING_PREAMBLE (str); + _dbus_assert (i <= real->len); + _dbus_assert (i >= 0); + + if (!open_gap (1, real, i)) + return FALSE; + + real->str[i] = byte; + + return TRUE; +} + /** * Like _dbus_string_get_data(), but removes the * gotten data from the original string. The caller @@ -875,43 +900,68 @@ _dbus_string_set_length (DBusString *str, } static dbus_bool_t -align_length_then_lengthen (DBusString *str, - int alignment, - int then_lengthen_by) +align_insert_point_then_open_gap (DBusString *str, + int *insert_at_p, + int alignment, + int gap_size) { unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */ + unsigned long gap_pos; + int insert_at; int delta; DBUS_STRING_PREAMBLE (str); _dbus_assert (alignment >= 1); _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */ - new_len = _DBUS_ALIGN_VALUE (real->len, alignment); - if (_DBUS_UNLIKELY (new_len > (unsigned long) real->max_length - then_lengthen_by)) + insert_at = *insert_at_p; + + _dbus_assert (insert_at <= real->len); + + gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment); + new_len = real->len + (gap_pos - insert_at) + gap_size; + + if (_DBUS_UNLIKELY (new_len > (unsigned long) real->max_length)) return FALSE; - new_len += then_lengthen_by; delta = new_len - real->len; _dbus_assert (delta >= 0); - if (delta == 0) - return TRUE; + if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */ + { + _dbus_assert (((unsigned long) *insert_at_p) == gap_pos); + return TRUE; + } - if (_DBUS_UNLIKELY (!set_length (real, new_len))) + if (_DBUS_UNLIKELY (!open_gap (new_len - real->len, + real, insert_at))) return FALSE; - /* delta == padding + then_lengthen_by - * new_len == old_len + padding + then_lengthen_by - * nul the padding if we had to add any padding - */ - if (then_lengthen_by < delta) + /* nul the padding if we had to add any padding */ + if (gap_size < delta) { - memset (&real->str[new_len - delta], '\0', - delta - then_lengthen_by); + memset (&real->str[insert_at], '\0', + gap_pos - insert_at); } - + + *insert_at_p = gap_pos; + return TRUE; } +static dbus_bool_t +align_length_then_lengthen (DBusString *str, + int alignment, + int then_lengthen_by) +{ + int insert_at; + + insert_at = _dbus_string_get_length (str); + + return align_insert_point_then_open_gap (str, + &insert_at, + alignment, then_lengthen_by); +} + /** * Align the length of a string to a specific alignment (typically 4 or 8) * by appending nul bytes to the string. @@ -927,6 +977,26 @@ _dbus_string_align_length (DBusString *str, return align_length_then_lengthen (str, alignment, 0); } +/** + * Preallocate extra_bytes such that a future lengthening of the + * string by extra_bytes is guaranteed to succeed without an out of + * memory error. + * + * @param str a string + * @param extra_bytes bytes to alloc + * @returns #FALSE if no memory + */ +dbus_bool_t +_dbus_string_alloc_space (DBusString *str, + int extra_bytes) +{ + if (!_dbus_string_lengthen (str, extra_bytes)) + return FALSE; + _dbus_string_shorten (str, extra_bytes); + + return TRUE; +} + static dbus_bool_t append (DBusRealString *real, const char *buffer, @@ -968,6 +1038,31 @@ _dbus_string_append (DBusString *str, return append (real, buffer, buffer_len); } +#define ASSIGN_4_OCTETS(p, octets) \ + *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets)); + +#ifdef DBUS_HAVE_INT64 +#define ASSIGN_8_OCTETS(p, octets) \ + *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets)); +#else +#define ASSIGN_8_OCTETS(p, octets) \ +do { \ + unsigned char *b; \ + \ + b = p; \ + \ + *b++ = octets[0]; \ + *b++ = octets[1]; \ + *b++ = octets[2]; \ + *b++ = octets[3]; \ + *b++ = octets[4]; \ + *b++ = octets[5]; \ + *b++ = octets[6]; \ + *b++ = octets[7]; \ + _dbus_assert (b == p + 8); \ +} while (0) +#endif /* DBUS_HAVE_INT64 */ + /** * Appends 4 bytes aligned on a 4 byte boundary * with any alignment padding initialized to 0. @@ -980,14 +1075,12 @@ dbus_bool_t _dbus_string_append_4_aligned (DBusString *str, const unsigned char octets[4]) { - dbus_uint32_t *p; DBUS_STRING_PREAMBLE (str); if (!align_length_then_lengthen (str, 4, 4)) return FALSE; - p = (dbus_uint32_t*) (real->str + (real->len - 4)); - *p = *((dbus_uint32_t*)octets); + ASSIGN_4_OCTETS (real->str + (real->len - 4), octets); return TRUE; } @@ -997,41 +1090,65 @@ _dbus_string_append_4_aligned (DBusString *str, * with any alignment padding initialized to 0. * * @param str the DBusString - * @param octets 4 bytes to append + * @param octets 8 bytes to append * @returns #FALSE if not enough memory. */ dbus_bool_t _dbus_string_append_8_aligned (DBusString *str, const unsigned char octets[8]) { -#ifdef DBUS_HAVE_INT64 - dbus_uint64_t *p; DBUS_STRING_PREAMBLE (str); if (!align_length_then_lengthen (str, 8, 8)) return FALSE; - p = (dbus_uint64_t*) (real->str + (real->len - 8)); - *p = *((dbus_uint64_t*)octets); -#else - unsigned char *p; + ASSIGN_8_OCTETS (real->str + (real->len - 8), octets); + + return TRUE; +} + +/** + * Inserts 4 bytes aligned on a 4 byte boundary + * with any alignment padding initialized to 0. + * + * @param str the DBusString + * @param octets 4 bytes to insert + * @returns #FALSE if not enough memory. + */ +dbus_bool_t +_dbus_string_insert_4_aligned (DBusString *str, + int insert_at, + const unsigned char octets[4]) +{ DBUS_STRING_PREAMBLE (str); - if (!align_length_then_lengthen (str, 8, 8)) + if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4)) return FALSE; - p = real->str + (real->len - 8); - - *p++ = octets[0]; - *p++ = octets[1]; - *p++ = octets[2]; - *p++ = octets[3]; - *p++ = octets[4]; - *p++ = octets[5]; - *p++ = octets[6]; - *p++ = octets[7]; - _dbus_assert (p == (real->str + real->len)); -#endif + ASSIGN_4_OCTETS (real->str + insert_at, octets); + + return TRUE; +} + +/** + * Inserts 8 bytes aligned on an 8 byte boundary + * with any alignment padding initialized to 0. + * + * @param str the DBusString + * @param octets 8 bytes to insert + * @returns #FALSE if not enough memory. + */ +dbus_bool_t +_dbus_string_insert_8_aligned (DBusString *str, + int insert_at, + const unsigned char octets[8]) +{ + DBUS_STRING_PREAMBLE (str); + + if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8)) + return FALSE; + + ASSIGN_8_OCTETS (real->str + insert_at, octets); return TRUE; } diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h index c30a63fe..2b8b09f5 100644 --- a/dbus/dbus-string.h +++ b/dbus/dbus-string.h @@ -90,6 +90,9 @@ dbus_bool_t _dbus_string_insert_bytes (DBusString *str, int i, int n_bytes, unsigned char byte); +dbus_bool_t _dbus_string_insert_byte (DBusString *str, + int i, + unsigned char byte); dbus_bool_t _dbus_string_steal_data (DBusString *str, char **data_return); dbus_bool_t _dbus_string_steal_data_len (DBusString *str, @@ -117,6 +120,8 @@ dbus_bool_t _dbus_string_set_length (DBusString *str, int length); dbus_bool_t _dbus_string_align_length (DBusString *str, int alignment); +dbus_bool_t _dbus_string_alloc_space (DBusString *str, + int extra_bytes); dbus_bool_t _dbus_string_append (DBusString *str, const char *buffer); dbus_bool_t _dbus_string_append_len (DBusString *str, @@ -142,6 +147,12 @@ dbus_bool_t _dbus_string_append_printf (DBusString *str, dbus_bool_t _dbus_string_append_printf_valist (DBusString *str, const char *format, va_list args); +dbus_bool_t _dbus_string_insert_4_aligned (DBusString *str, + int insert_at, + const unsigned char octets[4]); +dbus_bool_t _dbus_string_insert_8_aligned (DBusString *str, + int insert_at, + const unsigned char octets[8]); void _dbus_string_delete (DBusString *str, int start, int len); -- 2.34.1