diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c index ea18dbf..a37ff02 100644 --- a/dbus/dbus-marshal-basic.c +++ b/dbus/dbus-marshal-basic.c @@ -1213,6 +1213,7 @@ _dbus_type_get_alignment (int typecode) case DBUS_TYPE_STRING: case DBUS_TYPE_OBJECT_PATH: case DBUS_TYPE_ARRAY: + case DBUS_TYPE_MAYBE: return 4; case DBUS_TYPE_INT64: case DBUS_TYPE_UINT64: @@ -1260,6 +1261,7 @@ _dbus_type_is_valid (int typecode) case DBUS_TYPE_OBJECT_PATH: case DBUS_TYPE_SIGNATURE: case DBUS_TYPE_ARRAY: + case DBUS_TYPE_MAYBE: case DBUS_TYPE_STRUCT: case DBUS_TYPE_DICT_ENTRY: case DBUS_TYPE_VARIANT: @@ -1314,6 +1316,8 @@ _dbus_type_to_string (int typecode) return "dict_entry"; case DBUS_TYPE_ARRAY: return "array"; + case DBUS_TYPE_MAYBE: + return "maybe"; case DBUS_TYPE_VARIANT: return "variant"; case DBUS_STRUCT_BEGIN_CHAR: diff --git a/dbus/dbus-marshal-byteswap.c b/dbus/dbus-marshal-byteswap.c index 22d7e22..fadd437 100644 --- a/dbus/dbus-marshal-byteswap.c +++ b/dbus/dbus-marshal-byteswap.c @@ -83,6 +83,7 @@ byteswap_body_helper (DBusTypeReader *reader, break; case DBUS_TYPE_ARRAY: + case DBUS_TYPE_MAYBE: case DBUS_TYPE_STRING: case DBUS_TYPE_OBJECT_PATH: { @@ -95,7 +96,7 @@ byteswap_body_helper (DBusTypeReader *reader, *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p)); p += 4; - if (current_type == DBUS_TYPE_ARRAY) + if (DBUS_TYPE_IS_ARRAY (current_type)) { int elem_type; int alignment; diff --git a/dbus/dbus-marshal-header.c b/dbus/dbus-marshal-header.c index 3f31d7a..c2b10e6 100644 --- a/dbus/dbus-marshal-header.c +++ b/dbus/dbus-marshal-header.c @@ -1099,7 +1099,7 @@ _dbus_header_load (DBusHeader *header, goto invalid; } - _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_ARRAY); + _dbus_assert (DBUS_TYPE_IS_ARRAY (_dbus_type_reader_get_current_type (&reader))); _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FIELDS_ARRAY_LENGTH_OFFSET); _dbus_type_reader_recurse (&reader, &array_reader); diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c index cb10854..01b2286 100644 --- a/dbus/dbus-marshal-recursive.c +++ b/dbus/dbus-marshal-recursive.c @@ -340,7 +340,7 @@ _dbus_type_signature_next (const char *type_str, _dbus_assert (*p != DBUS_STRUCT_END_CHAR); _dbus_assert (*p != DBUS_DICT_ENTRY_END_CHAR); - while (*p == DBUS_TYPE_ARRAY) + while (DBUS_TYPE_IS_ARRAY (*p)) ++p; _dbus_assert (*p != DBUS_STRUCT_END_CHAR); @@ -463,6 +463,7 @@ base_reader_next (DBusTypeReader *reader, break; case DBUS_TYPE_ARRAY: + case DBUS_TYPE_MAYBE: { if (!reader->klass->types_only) _dbus_marshal_skip_array (reader->value_str, @@ -584,6 +585,7 @@ array_reader_next (DBusTypeReader *reader, break; case DBUS_TYPE_ARRAY: + case DBUS_TYPE_MAYBE: { _dbus_marshal_skip_array (reader->value_str, _dbus_first_type_in_signature (reader->type_str, @@ -809,7 +811,7 @@ _dbus_type_reader_get_element_type (const DBusTypeReader *reader) { int element_type; - _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY); + _dbus_assert (DBUS_TYPE_IS_ARRAY (_dbus_type_reader_get_current_type (reader))); element_type = _dbus_first_type_in_signature (reader->type_str, reader->type_pos + 1); @@ -995,6 +997,7 @@ _dbus_type_reader_recurse (DBusTypeReader *reader, sub->klass = &dict_entry_reader_class; break; case DBUS_TYPE_ARRAY: + case DBUS_TYPE_MAYBE: if (reader->klass->types_only) sub->klass = &array_types_only_reader_class; else @@ -1632,7 +1635,7 @@ writer_recurse_init_and_check (DBusTypeWriter *writer, sub->container_type = container_type; if (writer->type_pos_is_expectation || - (sub->container_type == DBUS_TYPE_ARRAY || sub->container_type == DBUS_TYPE_VARIANT)) + (DBUS_TYPE_IS_ARRAY (sub->container_type) || sub->container_type == DBUS_TYPE_VARIANT)) sub->type_pos_is_expectation = TRUE; else sub->type_pos_is_expectation = FALSE; @@ -1733,7 +1736,7 @@ write_or_verify_typecode (DBusTypeWriter *writer, * so the expected type doesn't change; if inside a struct or something * below an array, we need to move through said struct or something. */ - if (writer->container_type != DBUS_TYPE_ARRAY) + if (!DBUS_TYPE_IS_ARRAY (writer->container_type)) writer->type_pos += 1; } else @@ -1794,6 +1797,7 @@ writer_recurse_struct_or_dict_entry (DBusTypeWriter *writer, static dbus_bool_t writer_recurse_array (DBusTypeWriter *writer, + int array_type, const DBusString *contained_type, int contained_type_start, int contained_type_len, @@ -1805,7 +1809,7 @@ writer_recurse_array (DBusTypeWriter *writer, int aligned; #ifndef DBUS_DISABLE_CHECKS - if (writer->container_type == DBUS_TYPE_ARRAY && + if (DBUS_TYPE_IS_ARRAY (writer->container_type) && writer->type_str) { if (!_dbus_string_equal_substring (contained_type, @@ -1850,7 +1854,7 @@ writer_recurse_array (DBusTypeWriter *writer, if (!_dbus_string_insert_byte (writer->type_str, writer->type_pos, - DBUS_TYPE_ARRAY)) + array_type)) _dbus_assert_not_reached ("failed to insert array typecode after prealloc"); if (!_dbus_string_copy_len (contained_type, @@ -1865,7 +1869,7 @@ writer_recurse_array (DBusTypeWriter *writer, /* If the parent is an array, we hold type_pos pointing at the array element type; * otherwise advance it to reflect the array value we just recursed into */ - if (writer->container_type != DBUS_TYPE_ARRAY) + if (!DBUS_TYPE_IS_ARRAY (writer->container_type)) writer->type_pos += 1 + contained_type_len; else _dbus_assert (writer->type_pos_is_expectation); /* because it's an array */ @@ -2064,7 +2068,8 @@ _dbus_type_writer_recurse_contained_len (DBusTypeWriter *writer, sub); break; case DBUS_TYPE_ARRAY: - return writer_recurse_array (writer, + case DBUS_TYPE_MAYBE: + return writer_recurse_array (writer, container_type, contained_type, contained_type_start, contained_type_len, sub, is_array_append); break; @@ -2148,7 +2153,7 @@ _dbus_type_writer_append_array (DBusTypeWriter *writer, static int writer_get_array_len (DBusTypeWriter *writer) { - _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY); + _dbus_assert (DBUS_TYPE_IS_ARRAY (writer->container_type)); return writer->value_pos - writer->u.array.start_pos; } @@ -2188,7 +2193,7 @@ _dbus_type_writer_unrecurse (DBusTypeWriter *writer, if (!write_or_verify_typecode (sub, DBUS_DICT_ENTRY_END_CHAR)) return FALSE; } - else if (sub->container_type == DBUS_TYPE_ARRAY) + else if (DBUS_TYPE_IS_ARRAY (sub->container_type)) { if (sub->u.array.len_pos >= 0) /* len_pos == -1 if we weren't enabled when we passed it */ { @@ -2346,7 +2351,7 @@ _dbus_type_writer_write_fixed_multi (DBusTypeWriter *writer, const void *value, int n_elements) { - _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY); + _dbus_assert (DBUS_TYPE_IS_ARRAY (writer->container_type)); _dbus_assert (dbus_type_is_fixed (element_type)); _dbus_assert (writer->type_pos_is_expectation); _dbus_assert (n_elements >= 0); @@ -2468,7 +2473,7 @@ writer_write_reader_helper (DBusTypeWriter *writer, _dbus_type_reader_recurse (reader, &subreader); - if (current_type == DBUS_TYPE_ARRAY) + if (DBUS_TYPE_IS_ARRAY (current_type)) { reader_array_len_pos = ARRAY_READER_LEN_POS (&subreader); reader_array_start_pos = subreader.u.array.start_pos; @@ -2537,7 +2542,7 @@ writer_write_reader_helper (DBusTypeWriter *writer, */ if (start_after != NULL && !enabled_at_recurse && past_start_after && - current_type == DBUS_TYPE_ARRAY && + DBUS_TYPE_IS_ARRAY (current_type) && fixups != NULL) { DBusArrayLenFixup fixup; diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c index aa470fc..c911790 100644 --- a/dbus/dbus-marshal-validate.c +++ b/dbus/dbus-marshal-validate.c @@ -112,6 +112,7 @@ _dbus_validate_signature_with_reason (const DBusString *type_str, break; case DBUS_TYPE_ARRAY: + case DBUS_TYPE_MAYBE: array_depth += 1; if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) { @@ -212,8 +213,8 @@ _dbus_validate_signature_with_reason (const DBusString *type_str, goto out; } - if (*p != DBUS_TYPE_ARRAY && - *p != DBUS_DICT_ENTRY_BEGIN_CHAR && + if (!DBUS_TYPE_IS_ARRAY (*p) && + *p != DBUS_DICT_ENTRY_BEGIN_CHAR && *p != DBUS_STRUCT_BEGIN_CHAR) { element_count = @@ -231,7 +232,7 @@ _dbus_validate_signature_with_reason (const DBusString *type_str, if (array_depth > 0) { - if (*p == DBUS_TYPE_ARRAY && p != end) + if (DBUS_TYPE_IS_ARRAY (*p) && p != end) { const char *p1; p1 = p + 1; @@ -280,7 +281,7 @@ _dbus_validate_signature_with_reason (const DBusString *type_str, goto out; } - _dbus_assert (last != DBUS_TYPE_ARRAY); + _dbus_assert (!DBUS_TYPE_IS_ARRAY (last)); _dbus_assert (last != DBUS_STRUCT_BEGIN_CHAR); _dbus_assert (last != DBUS_DICT_ENTRY_BEGIN_CHAR); @@ -354,6 +355,7 @@ validate_body_helper (DBusTypeReader *reader, break; case DBUS_TYPE_ARRAY: + case DBUS_TYPE_MAYBE: case DBUS_TYPE_STRING: case DBUS_TYPE_OBJECT_PATH: { @@ -375,7 +377,7 @@ validate_body_helper (DBusTypeReader *reader, /* p may now be == end */ _dbus_assert (p <= end); - if (current_type == DBUS_TYPE_ARRAY) + if (DBUS_TYPE_IS_ARRAY (current_type)) { int array_elem_type = _dbus_type_reader_get_element_type (reader); @@ -423,7 +425,7 @@ validate_body_helper (DBusTypeReader *reader, p += claimed_len; } - else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0) + else if (DBUS_TYPE_IS_ARRAY (current_type) && claimed_len > 0) { DBusTypeReader sub; DBusValidity validity; @@ -488,7 +490,7 @@ validate_body_helper (DBusTypeReader *reader, } /* check nul termination */ - if (current_type != DBUS_TYPE_ARRAY) + if (!DBUS_TYPE_IS_ARRAY (current_type)) { if (p == end) return DBUS_INVALID_NOT_ENOUGH_DATA; diff --git a/dbus/dbus-message-factory.c b/dbus/dbus-message-factory.c index 7432cf2..b414422 100644 --- a/dbus/dbus-message-factory.c +++ b/dbus/dbus-message-factory.c @@ -944,6 +944,7 @@ static const int typecodes[] = { DBUS_TYPE_OBJECT_PATH, DBUS_TYPE_SIGNATURE, DBUS_TYPE_ARRAY, + DBUS_TYPE_MAYBE, DBUS_TYPE_VARIANT, DBUS_STRUCT_BEGIN_CHAR, DBUS_STRUCT_END_CHAR, diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 3b5941b..7be2490 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -791,7 +791,7 @@ _dbus_message_iter_get_args_valist (DBusMessageIter *iter, _dbus_type_reader_read_basic (&real->u.reader, ptr); } - else if (spec_type == DBUS_TYPE_ARRAY) + else if (DBUS_TYPE_IS_ARRAY (spec_type)) { int element_type; int spec_element_type; @@ -887,6 +887,14 @@ _dbus_message_iter_get_args_valist (DBusMessageIter *iter, _dbus_assert (i == n_elements); _dbus_assert (str_array[i] == NULL); + if (spec_type == DBUS_TYPE_MAYBE && _DBUS_UNLIKELY (n_elements > 1)) + { + dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, + "Maybe \"%s\" contains multiple elements\n", + _dbus_type_to_string (spec_element_type)); + goto out; + } + *str_array_p = str_array; *n_elements_p = n_elements; } @@ -1695,7 +1703,7 @@ dbus_message_append_args_valist (DBusMessage *message, value)) goto failed; } - else if (type == DBUS_TYPE_ARRAY) + else if (DBUS_TYPE_IS_ARRAY (type)) { int element_type; DBusMessageIter array; @@ -1705,8 +1713,9 @@ dbus_message_append_args_valist (DBusMessage *message, buf[0] = element_type; buf[1] = '\0'; + if (!dbus_message_iter_open_container (&iter, - DBUS_TYPE_ARRAY, + type, buf, &array)) goto failed; @@ -1886,6 +1895,7 @@ _dbus_message_iter_init_common (DBusMessage *message, real->message = message; real->changed_stamp = message->changed_stamp; real->iter_type = iter_type; + real->sig_refcount = 0; } @@ -2012,7 +2022,7 @@ dbus_message_iter_get_element_type (DBusMessageIter *iter) _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID); - _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID); + _dbus_return_val_if_fail (DBUS_TYPE_IS_ARRAY (dbus_message_iter_get_arg_type (iter)), DBUS_TYPE_INVALID); return _dbus_type_reader_get_element_type (&real->u.reader); } @@ -2619,7 +2629,8 @@ dbus_message_iter_append_fixed_array (DBusMessageIter *iter, _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE); - _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE); + _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY + || (real->u.writer.container_type == DBUS_TYPE_MAYBE && n_elements < 2), FALSE); _dbus_return_val_if_fail (value != NULL, FALSE); _dbus_return_val_if_fail (n_elements >= 0, FALSE); _dbus_return_val_if_fail (n_elements <= @@ -2672,17 +2683,23 @@ dbus_message_iter_open_container (DBusMessageIter *iter, contained_signature == NULL) || (type == DBUS_TYPE_VARIANT && contained_signature != NULL) || - (type == DBUS_TYPE_ARRAY && + (DBUS_TYPE_IS_ARRAY (type) && contained_signature != NULL), FALSE); /* this would fail if the contained_signature is a dict entry, since * dict entries are invalid signatures standalone (they must be in * an array) */ - _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || + _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && + contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || (contained_signature == NULL || _dbus_check_is_valid_signature (contained_signature)), FALSE); + /* the containted signature of a maybe must contain exactly one element */ + _dbus_return_val_if_fail (((type == DBUS_TYPE_MAYBE && + (contained_signature[0] != '\0' && + contained_signature[1] == '\0')) || + type != DBUS_TYPE_MAYBE), FALSE); if (!_dbus_message_iter_open_signature (real)) return FALSE; diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h index 17798e9..c0b2cfb 100644 --- a/dbus/dbus-protocol.h +++ b/dbus/dbus-protocol.h @@ -120,11 +120,19 @@ extern "C" { #define DBUS_TYPE_ARRAY ((int) 'a') /** #DBUS_TYPE_ARRAY as a string literal instead of a int literal */ #define DBUS_TYPE_ARRAY_AS_STRING "a" +/** Type code marking a D-Bus maybe type */ +#define DBUS_TYPE_MAYBE ((int) 'm') +/** #DBUS_TYPE_MAYBE as a string literal instead of an int literal */ +#define DBUS_TYPE_MAYBE_AS_STRING "m" /** Type code marking a D-Bus variant type */ #define DBUS_TYPE_VARIANT ((int) 'v') /** #DBUS_TYPE_VARIANT as a string literal instead of a int literal */ #define DBUS_TYPE_VARIANT_AS_STRING "v" +#define DBUS_TYPE_IS_ARRAY(typeliteral) \ + (typeliteral == DBUS_TYPE_ARRAY \ + || typeliteral == DBUS_TYPE_MAYBE) + /** STRUCT and DICT_ENTRY are sort of special since their codes can't * appear in a type string, instead * DBUS_STRUCT_BEGIN_CHAR/DBUS_DICT_ENTRY_BEGIN_CHAR have to appear diff --git a/dbus/dbus-signature.c b/dbus/dbus-signature.c index ddc0bcc..9e476c9 100644 --- a/dbus/dbus-signature.c +++ b/dbus/dbus-signature.c @@ -44,7 +44,7 @@ typedef struct ((typecode) == DBUS_TYPE_STRUCT || \ (typecode) == DBUS_TYPE_DICT_ENTRY || \ (typecode) == DBUS_TYPE_VARIANT || \ - (typecode) == DBUS_TYPE_ARRAY) + DBUS_TYPE_IS_ARRAY (typecode)) /** @@ -137,7 +137,7 @@ dbus_signature_iter_get_signature (const DBusSignatureIter *iter) * getting its current type. * * Undefined behavior results if you invoke this function when the - * current type of the iterator is not #DBUS_TYPE_ARRAY. + * current type of the iterator is not an array, see #DBUS_TYPE_IS_ARRAY. * * @param iter pointer to an iterator * @returns current array element type @@ -147,7 +147,7 @@ dbus_signature_iter_get_element_type (const DBusSignatureIter *iter) { DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter; - _dbus_return_val_if_fail (dbus_signature_iter_get_current_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID); + _dbus_return_val_if_fail (DBUS_TYPE_IS_ARRAY (dbus_signature_iter_get_current_type (iter)), DBUS_TYPE_INVALID); return _dbus_first_type_in_signature_c_str (real_iter->pos, 1); } @@ -216,7 +216,7 @@ dbus_signature_iter_recurse (const DBusSignatureIter *iter, real_sub_iter->in_array = FALSE; real_sub_iter->pos++; - if (dbus_signature_iter_get_current_type (iter) == DBUS_TYPE_ARRAY) + if (DBUS_TYPE_IS_ARRAY (dbus_signature_iter_get_current_type (iter))) real_sub_iter->in_array = TRUE; }