diff options
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | dbus/dbus-marshal-header.c | 16 | ||||
-rw-r--r-- | dbus/dbus-marshal-validate.c | 12 | ||||
-rw-r--r-- | dbus/dbus-marshal-validate.h | 35 | ||||
-rw-r--r-- | dbus/dbus-message-factory.c | 519 | ||||
-rw-r--r-- | dbus/dbus-message-util.c | 55 | ||||
-rw-r--r-- | dbus/dbus-message.c | 8 | ||||
-rw-r--r-- | dbus/dbus-string-util.c | 43 |
8 files changed, 654 insertions, 51 deletions
@@ -1,5 +1,22 @@ 2005-02-05 Havoc Pennington <hp@redhat.com> + * dbus/dbus-message-factory.c (generate_special): more test cases, + increasing coverage + + * dbus/dbus-marshal-validate.c (validate_body_helper): return the + reason why a signature was invalid + + * dbus/dbus-marshal-header.c (load_and_validate_field): fix to + skip the length of the string before we look at it in validation + + * dbus/dbus-string-util.c (_dbus_string_test): add tests for + equal_substring + + * dbus/dbus-message.c (_dbus_message_loader_new): default + max_message_length to DBUS_MAXIMUM_MESSAGE_LENGTH + +2005-02-05 Havoc Pennington <hp@redhat.com> + * dbus/dbus-marshal-validate.c (validate_body_helper): fix crash if the signature of a variant was empty (_dbus_validate_signature_with_reason): catch "(a)" (array inside diff --git a/dbus/dbus-marshal-header.c b/dbus/dbus-marshal-header.c index f32e7aa8..10d9e20b 100644 --- a/dbus/dbus-marshal-header.c +++ b/dbus/dbus-marshal-header.c @@ -773,6 +773,7 @@ load_and_validate_field (DBusHeader *header, int expected_type; const DBusString *value_str; int value_pos; + int str_data_pos; dbus_uint32_t v_UINT32; int bad_string_code; dbus_bool_t (* string_validation_func) (const DBusString *str, @@ -812,6 +813,7 @@ load_and_validate_field (DBusHeader *header, v_UINT32 = 0; value_str = NULL; value_pos = -1; + str_data_pos = -1; bad_string_code = DBUS_VALID; if (expected_type == DBUS_TYPE_UINT32) @@ -825,6 +827,7 @@ load_and_validate_field (DBusHeader *header, { _dbus_header_get_field_raw (header, field, &value_str, &value_pos); + str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4; } else { @@ -844,7 +847,7 @@ load_and_validate_field (DBusHeader *header, if (_dbus_string_equal_substring (&_dbus_local_interface_str, 0, _dbus_string_get_length (&_dbus_local_interface_str), - value_str, value_pos)) + value_str, str_data_pos)) { _dbus_verbose ("Message is on the local interface\n"); return DBUS_INVALID_USES_LOCAL_INTERFACE; @@ -870,13 +873,10 @@ load_and_validate_field (DBusHeader *header, /* OBJECT_PATH was validated generically due to its type */ string_validation_func = NULL; - _dbus_verbose ("value_str %p value_pos %d value_str_len %d\n", - value_str, value_pos, - _dbus_string_get_length (value_str)); if (_dbus_string_equal_substring (&_dbus_local_path_str, 0, _dbus_string_get_length (&_dbus_local_path_str), - value_str, value_pos)) + value_str, str_data_pos)) { _dbus_verbose ("Message is from the local path\n"); return DBUS_INVALID_USES_LOCAL_PATH; @@ -910,7 +910,11 @@ load_and_validate_field (DBusHeader *header, len = _dbus_marshal_read_uint32 (value_str, value_pos, header->byte_order, NULL); - if (!(*string_validation_func) (value_str, value_pos + 4, len)) +#if 0 + _dbus_verbose ("Validating string header field; code %d if fails\n", + bad_string_code); +#endif + if (!(*string_validation_func) (value_str, str_data_pos, len)) return bad_string_code; } diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c index f7b46c0b..c1d95820 100644 --- a/dbus/dbus-marshal-validate.c +++ b/dbus/dbus-marshal-validate.c @@ -335,6 +335,7 @@ validate_body_helper (DBusTypeReader *reader, { dbus_uint32_t claimed_len; DBusString str; + DBusValidity validity; claimed_len = *p; ++p; @@ -344,9 +345,12 @@ validate_body_helper (DBusTypeReader *reader, return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS; _dbus_string_init_const_len (&str, p, claimed_len); - if (!_dbus_validate_signature (&str, 0, - _dbus_string_get_length (&str))) - return DBUS_INVALID_BAD_SIGNATURE; + validity = + _dbus_validate_signature_with_reason (&str, 0, + _dbus_string_get_length (&str)); + + if (validity != DBUS_VALID) + return validity; p += claimed_len; @@ -389,7 +393,7 @@ validate_body_helper (DBusTypeReader *reader, return DBUS_INVALID_VARIANT_SIGNATURE_BAD; p += claimed_len; - + if (*p != DBUS_TYPE_INVALID) return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL; ++p; diff --git a/dbus/dbus-marshal-validate.h b/dbus/dbus-marshal-validate.h index 55739d31..8989d508 100644 --- a/dbus/dbus-marshal-validate.h +++ b/dbus/dbus-marshal-validate.h @@ -48,6 +48,7 @@ typedef enum */ typedef enum { +#define _DBUS_NEGATIVE_VALIDITY_COUNT 3 DBUS_INVALID_FOR_UNKNOWN_REASON = -3, DBUS_VALID_BUT_INCOMPLETE = -2, DBUS_VALIDITY_UNKNOWN = -1, @@ -91,23 +92,23 @@ typedef enum DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM = 37, DBUS_INVALID_BAD_PATH = 38, DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS = 39, - DBUS_INVALID_BAD_SIGNATURE = 40, - DBUS_INVALID_BAD_UTF8_IN_STRING = 41, - DBUS_INVALID_ARRAY_LENGTH_INCORRECT = 42, - DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS = 43, - DBUS_INVALID_VARIANT_SIGNATURE_BAD = 44, - DBUS_INVALID_VARIANT_SIGNATURE_EMPTY = 45, - DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES = 46, - DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL = 47, - DBUS_INVALID_STRING_MISSING_NUL = 48, - DBUS_INVALID_SIGNATURE_MISSING_NUL = 49, - DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION = 50, - DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED = 51, - DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED = 52, - DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS = 53, - DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD = 54, - DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS = 55, - DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY = 56 + DBUS_INVALID_BAD_UTF8_IN_STRING = 40, + DBUS_INVALID_ARRAY_LENGTH_INCORRECT = 41, + DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS = 42, + DBUS_INVALID_VARIANT_SIGNATURE_BAD = 43, + DBUS_INVALID_VARIANT_SIGNATURE_EMPTY = 44, + DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES = 45, + DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL = 46, + DBUS_INVALID_STRING_MISSING_NUL = 47, + DBUS_INVALID_SIGNATURE_MISSING_NUL = 48, + DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION = 49, + DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED = 50, + DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED = 51, + DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS = 52, + DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD = 53, + DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS = 54, + DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY = 55, + DBUS_VALIDITY_LAST } DBusValidity; DBusValidity _dbus_validate_signature_with_reason (const DBusString *type_str, diff --git a/dbus/dbus-message-factory.c b/dbus/dbus-message-factory.c index 26109815..adcb9b2e 100644 --- a/dbus/dbus-message-factory.c +++ b/dbus/dbus-message-factory.c @@ -35,7 +35,9 @@ typedef enum } ChangeType; #define BYTE_ORDER_OFFSET 0 +#define TYPE_OFFSET 1 #define BODY_LENGTH_OFFSET 4 +#define FIELDS_ARRAY_LENGTH_OFFSET 12 static void iter_recurse (DBusMessageDataIter *iter) @@ -165,11 +167,12 @@ generate_many_bodies_inner (DBusMessageDataIter *iter, DBusMessage *message; DBusString signature; DBusString body; - - message = dbus_message_new_method_call ("org.freedesktop.Foo", + + /* Keeping this small makes things go faster */ + message = dbus_message_new_method_call ("o.z.F", "/", - "org.freedesktop.Blah", - "NahNahNah"); + "o.z.B", + "Nah"); if (message == NULL) _dbus_assert_not_reached ("oom"); @@ -212,6 +215,26 @@ generate_many_bodies_inner (DBusMessageDataIter *iter, return *message_p != NULL; } +static void +generate_from_message (DBusString *data, + DBusValidity *expected_validity, + DBusMessage *message) +{ + _dbus_message_set_serial (message, 1); + _dbus_message_lock (message); + + *expected_validity = DBUS_VALID; + + /* move for efficiency, since we'll nuke the message anyway */ + if (!_dbus_string_move (&message->header.data, 0, + data, 0)) + _dbus_assert_not_reached ("oom"); + + if (!_dbus_string_copy (&message->body, 0, + data, _dbus_string_get_length (data))) + _dbus_assert_not_reached ("oom"); +} + static dbus_bool_t generate_outer (DBusMessageDataIter *iter, DBusString *data, @@ -228,19 +251,7 @@ generate_outer (DBusMessageDataIter *iter, _dbus_assert (message != NULL); - _dbus_message_set_serial (message, 1); - _dbus_message_lock (message); - - *expected_validity = DBUS_VALID; - - /* move for efficiency, since we'll nuke the message anyway */ - if (!_dbus_string_move (&message->header.data, 0, - data, 0)) - _dbus_assert_not_reached ("oom"); - - if (!_dbus_string_copy (&message->body, 0, - data, _dbus_string_get_length (data))) - _dbus_assert_not_reached ("oom"); + generate_from_message (data, expected_validity, message); dbus_message_unref (message); @@ -265,6 +276,334 @@ generate_many_bodies (DBusMessageDataIter *iter, generate_many_bodies_inner); } +static DBusMessage* +simple_method_call (void) +{ + DBusMessage *message; + /* Keeping this small makes stuff go faster */ + message = dbus_message_new_method_call ("o.b.Q", + "/f/b", + "o.b.Z", + "Fro"); + if (message == NULL) + _dbus_assert_not_reached ("oom"); + return message; +} + +static DBusMessage* +simple_signal (void) +{ + DBusMessage *message; + message = dbus_message_new_signal ("/f/b", + "o.b.Z", + "Fro"); + if (message == NULL) + _dbus_assert_not_reached ("oom"); + return message; +} + +static DBusMessage* +simple_method_return (void) +{ + DBusMessage *message; + message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN); + if (message == NULL) + _dbus_assert_not_reached ("oom"); + + set_reply_serial (message); + + return message; +} + +static dbus_bool_t +generate_special (DBusMessageDataIter *iter, + DBusString *data, + DBusValidity *expected_validity) +{ + int item_seq; + DBusMessage *message; + int pos; + dbus_int32_t v_INT32; + + _dbus_assert (_dbus_string_get_length (data) == 0); + + message = NULL; + pos = -1; + v_INT32 = 42; + item_seq = iter_get_sequence (iter); + + if (item_seq == 0) + { + message = simple_method_call (); + if (!dbus_message_append_args (message, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INVALID)) + _dbus_assert_not_reached ("oom"); + + _dbus_header_get_field_raw (&message->header, + DBUS_HEADER_FIELD_SIGNATURE, + NULL, &pos); + generate_from_message (data, expected_validity, message); + + /* set an invalid typecode */ + _dbus_string_set_byte (data, pos + 1, '$'); + + *expected_validity = DBUS_INVALID_UNKNOWN_TYPECODE; + } + else if (item_seq == 1) + { + char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH+1]; + const char *v_STRING; + int i; + + message = simple_method_call (); + if (!dbus_message_append_args (message, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INVALID)) + _dbus_assert_not_reached ("oom"); + + i = 0; + while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1)) + { + long_sig[i] = DBUS_TYPE_ARRAY; + ++i; + } + + v_STRING = long_sig; + if (!_dbus_header_set_field_basic (&message->header, + DBUS_HEADER_FIELD_SIGNATURE, + DBUS_TYPE_SIGNATURE, + &v_STRING)) + _dbus_assert_not_reached ("oom"); + + _dbus_header_get_field_raw (&message->header, + DBUS_HEADER_FIELD_SIGNATURE, + NULL, &pos); + generate_from_message (data, expected_validity, message); + + *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION; + } + else if (item_seq == 2) + { + char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2+3]; + const char *v_STRING; + int i; + + message = simple_method_call (); + if (!dbus_message_append_args (message, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INVALID)) + _dbus_assert_not_reached ("oom"); + + i = 0; + while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1)) + { + long_sig[i] = DBUS_STRUCT_BEGIN_CHAR; + ++i; + } + + long_sig[i] = DBUS_TYPE_INT32; + ++i; + + while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2 + 3)) + { + long_sig[i] = DBUS_STRUCT_END_CHAR; + ++i; + } + + v_STRING = long_sig; + if (!_dbus_header_set_field_basic (&message->header, + DBUS_HEADER_FIELD_SIGNATURE, + DBUS_TYPE_SIGNATURE, + &v_STRING)) + _dbus_assert_not_reached ("oom"); + + _dbus_header_get_field_raw (&message->header, + DBUS_HEADER_FIELD_SIGNATURE, + NULL, &pos); + generate_from_message (data, expected_validity, message); + + *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION; + } + else if (item_seq == 3) + { + message = simple_method_call (); + if (!dbus_message_append_args (message, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INVALID)) + _dbus_assert_not_reached ("oom"); + + _dbus_header_get_field_raw (&message->header, + DBUS_HEADER_FIELD_SIGNATURE, + NULL, &pos); + generate_from_message (data, expected_validity, message); + + _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR); + + *expected_validity = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED; + } + else if (item_seq == 4) + { + message = simple_method_call (); + if (!dbus_message_append_args (message, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INVALID)) + _dbus_assert_not_reached ("oom"); + + _dbus_header_get_field_raw (&message->header, + DBUS_HEADER_FIELD_SIGNATURE, + NULL, &pos); + generate_from_message (data, expected_validity, message); + + _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_END_CHAR); + + *expected_validity = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED; + } + else if (item_seq == 5) + { + message = simple_method_call (); + if (!dbus_message_append_args (message, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INT32, &v_INT32, + DBUS_TYPE_INVALID)) + _dbus_assert_not_reached ("oom"); + + _dbus_header_get_field_raw (&message->header, + DBUS_HEADER_FIELD_SIGNATURE, + NULL, &pos); + generate_from_message (data, expected_validity, message); + + _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR); + _dbus_string_set_byte (data, pos + 2, DBUS_STRUCT_END_CHAR); + + *expected_validity = DBUS_INVALID_STRUCT_HAS_NO_FIELDS; + } + else if (item_seq == 6) + { + message = simple_method_call (); + generate_from_message (data, expected_validity, message); + + _dbus_string_set_byte (data, TYPE_OFFSET, DBUS_MESSAGE_TYPE_INVALID); + + *expected_validity = DBUS_INVALID_BAD_MESSAGE_TYPE; + } + else if (item_seq == 7) + { + /* Messages of unknown type are considered valid */ + message = simple_method_call (); + generate_from_message (data, expected_validity, message); + + _dbus_string_set_byte (data, TYPE_OFFSET, 100); + + *expected_validity = DBUS_VALID; + } + else if (item_seq == 8) + { + message = simple_method_call (); + generate_from_message (data, expected_validity, message); + + _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET, + DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4, + message->byte_order); + _dbus_marshal_set_uint32 (data, FIELDS_ARRAY_LENGTH_OFFSET, + DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4, + message->byte_order); + *expected_validity = DBUS_INVALID_MESSAGE_TOO_LONG; + } + else if (item_seq == 9) + { + const char *v_STRING = "not a valid bus name"; + message = simple_method_call (); + + if (!_dbus_header_set_field_basic (&message->header, + DBUS_HEADER_FIELD_SENDER, + DBUS_TYPE_STRING, &v_STRING)) + _dbus_assert_not_reached ("oom"); + + generate_from_message (data, expected_validity, message); + + *expected_validity = DBUS_INVALID_BAD_SENDER; + } + else if (item_seq == 10) + { + message = simple_method_call (); + + if (!dbus_message_set_interface (message, DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL)) + _dbus_assert_not_reached ("oom"); + + generate_from_message (data, expected_validity, message); + + *expected_validity = DBUS_INVALID_USES_LOCAL_INTERFACE; + } + else if (item_seq == 11) + { + message = simple_method_call (); + + if (!dbus_message_set_path (message, DBUS_PATH_ORG_FREEDESKTOP_LOCAL)) + _dbus_assert_not_reached ("oom"); + + generate_from_message (data, expected_validity, message); + + *expected_validity = DBUS_INVALID_USES_LOCAL_PATH; + } + else if (item_seq == 12) + { + /* Method calls don't have to have interface */ + message = simple_method_call (); + + if (!dbus_message_set_interface (message, NULL)) + _dbus_assert_not_reached ("oom"); + + generate_from_message (data, expected_validity, message); + + *expected_validity = DBUS_VALID; + } + else if (item_seq == 13) + { + /* Signals require an interface */ + message = simple_signal (); + + if (!dbus_message_set_interface (message, NULL)) + _dbus_assert_not_reached ("oom"); + + generate_from_message (data, expected_validity, message); + + *expected_validity = DBUS_INVALID_MISSING_INTERFACE; + } + else if (item_seq == 14) + { + message = simple_method_return (); + + if (!_dbus_header_delete_field (&message->header, DBUS_HEADER_FIELD_REPLY_SERIAL)) + _dbus_assert_not_reached ("oom"); + + generate_from_message (data, expected_validity, message); + + *expected_validity = DBUS_INVALID_MISSING_REPLY_SERIAL; + } + else + { + return FALSE; + } + + if (message) + dbus_message_unref (message); + + iter_next (iter); + return TRUE; +} + static dbus_bool_t generate_wrong_length (DBusMessageDataIter *iter, DBusString *data, @@ -388,6 +727,145 @@ generate_byte_changed (DBusMessageDataIter *iter, return TRUE; } +static dbus_bool_t +find_next_typecode (DBusMessageDataIter *iter, + DBusString *data, + DBusValidity *expected_validity) +{ + int body_seq; + int byte_seq; + int base_depth; + + base_depth = iter->depth; + + restart: + _dbus_assert (iter->depth == (base_depth + 0)); + _dbus_string_set_length (data, 0); + + body_seq = iter_get_sequence (iter); + + if (!generate_many_bodies (iter, data, expected_validity)) + return FALSE; + /* Undo the "next" in generate_many_bodies */ + iter_set_sequence (iter, body_seq); + + iter_recurse (iter); + while (TRUE) + { + _dbus_assert (iter->depth == (base_depth + 1)); + + byte_seq = iter_get_sequence (iter); + + _dbus_assert (byte_seq <= _dbus_string_get_length (data)); + + if (byte_seq == _dbus_string_get_length (data)) + { + /* reset byte count */ + iter_set_sequence (iter, 0); + iter_unrecurse (iter); + _dbus_assert (iter->depth == (base_depth + 0)); + iter_next (iter); /* go to the next body */ + goto restart; + } + + _dbus_assert (byte_seq < _dbus_string_get_length (data)); + + if (_dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq))) + break; + else + iter_next (iter); + } + + _dbus_assert (byte_seq == iter_get_sequence (iter)); + _dbus_assert (byte_seq < _dbus_string_get_length (data)); + + iter_unrecurse (iter); + + _dbus_assert (iter->depth == (base_depth + 0)); + + return TRUE; +} + +static const int typecodes[] = { + DBUS_TYPE_INVALID, + DBUS_TYPE_BYTE, + DBUS_TYPE_BOOLEAN, + DBUS_TYPE_INT16, + DBUS_TYPE_UINT16, + DBUS_TYPE_INT32, + DBUS_TYPE_UINT32, + DBUS_TYPE_INT64, + DBUS_TYPE_UINT64, + DBUS_TYPE_DOUBLE, + DBUS_TYPE_STRING, + DBUS_TYPE_OBJECT_PATH, + DBUS_TYPE_SIGNATURE, + DBUS_TYPE_ARRAY, + DBUS_TYPE_VARIANT, + DBUS_STRUCT_BEGIN_CHAR, + DBUS_STRUCT_END_CHAR, + DBUS_DICT_ENTRY_BEGIN_CHAR, + DBUS_DICT_ENTRY_END_CHAR, + 255 /* random invalid typecode */ +}; + +static dbus_bool_t +generate_typecode_changed (DBusMessageDataIter *iter, + DBusString *data, + DBusValidity *expected_validity) +{ + int byte_seq; + int typecode_seq; + int base_depth; + + base_depth = iter->depth; + + restart: + _dbus_assert (iter->depth == (base_depth + 0)); + _dbus_string_set_length (data, 0); + + if (!find_next_typecode (iter, data, expected_validity)) + return FALSE; + + iter_recurse (iter); + byte_seq = iter_get_sequence (iter); + + _dbus_assert (byte_seq < _dbus_string_get_length (data)); + + iter_recurse (iter); + typecode_seq = iter_get_sequence (iter); + iter_next (iter); + + _dbus_assert (typecode_seq <= _DBUS_N_ELEMENTS (typecodes)); + + if (typecode_seq == _DBUS_N_ELEMENTS (typecodes)) + { + _dbus_assert (iter->depth == (base_depth + 2)); + iter_set_sequence (iter, 0); /* reset typecode sequence */ + iter_unrecurse (iter); + _dbus_assert (iter->depth == (base_depth + 1)); + iter_next (iter); /* go to the next byte_seq */ + iter_unrecurse (iter); + _dbus_assert (iter->depth == (base_depth + 0)); + goto restart; + } + + _dbus_assert (iter->depth == (base_depth + 2)); + iter_unrecurse (iter); + _dbus_assert (iter->depth == (base_depth + 1)); + iter_unrecurse (iter); + _dbus_assert (iter->depth == (base_depth + 0)); + +#if 0 + printf ("Changing byte %d in message %d to %c\n", + byte_seq, iter_get_sequence (iter), typecodes[typecode_seq]); +#endif + + _dbus_string_set_byte (data, byte_seq, typecodes[typecode_seq]); + *expected_validity = DBUS_VALIDITY_UNKNOWN; + return TRUE; +} + typedef struct { ChangeType type; @@ -528,9 +1006,14 @@ typedef struct static const DBusMessageGenerator generators[] = { { "trivial example of each message type", generate_trivial }, { "assorted arguments", generate_many_bodies }, + { "assorted special cases", generate_special }, { "each uint32 modified", generate_uint32_changed }, { "wrong body lengths", generate_wrong_length }, - { "each byte modified", generate_byte_changed } + { "each byte modified", generate_byte_changed }, +#if 0 + /* This is really expensive and doesn't add too much coverage */ + { "change each typecode", generate_typecode_changed } +#endif }; void diff --git a/dbus/dbus-message-util.c b/dbus/dbus-message-util.c index c646ebf9..69db2019 100644 --- a/dbus/dbus-message-util.c +++ b/dbus/dbus-message-util.c @@ -78,6 +78,45 @@ dbus_message_iter_get_args (DBusMessageIter *iter, #include <stdio.h> #include <stdlib.h> +static int validities_seen[DBUS_VALIDITY_LAST + _DBUS_NEGATIVE_VALIDITY_COUNT]; + +static void +reset_validities_seen (void) +{ + int i; + i = 0; + while (i < _DBUS_N_ELEMENTS (validities_seen)) + { + validities_seen[i] = 0; + ++i; + } +} + +static void +record_validity_seen (DBusValidity validity) +{ + validities_seen[validity + _DBUS_NEGATIVE_VALIDITY_COUNT] += 1; +} + +static void +print_validities_seen (dbus_bool_t not_seen) +{ + int i; + i = 0; + while (i < _DBUS_N_ELEMENTS (validities_seen)) + { + if ((i - _DBUS_NEGATIVE_VALIDITY_COUNT) == DBUS_VALIDITY_UNKNOWN || + (i - _DBUS_NEGATIVE_VALIDITY_COUNT) == DBUS_INVALID_FOR_UNKNOWN_REASON) + ; + else if ((not_seen && validities_seen[i] == 0) || + (!not_seen && validities_seen[i] > 0)) + printf ("validity %3d seen %d times\n", + i - _DBUS_NEGATIVE_VALIDITY_COUNT, + validities_seen[i]); + ++i; + } +} + static void check_memleaks (void) { @@ -130,6 +169,8 @@ check_have_valid_message (DBusMessageLoader *loader) goto failed; #endif + record_validity_seen (DBUS_VALID); + retval = TRUE; failed: @@ -153,6 +194,8 @@ check_invalid_message (DBusMessageLoader *loader, goto failed; } + record_validity_seen (loader->corruption_reason); + if (expected_validity != DBUS_INVALID_FOR_UNKNOWN_REASON && loader->corruption_reason != expected_validity) { @@ -190,6 +233,7 @@ check_incomplete_message (DBusMessageLoader *loader) goto failed; } + record_validity_seen (DBUS_VALID_BUT_INCOMPLETE); retval = TRUE; failed: @@ -212,8 +256,12 @@ check_loader_results (DBusMessageLoader *loader, else if (expected_validity == DBUS_VALIDITY_UNKNOWN) { /* here we just know we didn't segfault and that was the - * only test + * only test. Also, we record that we got coverage + * for the validity reason. */ + if (_dbus_message_loader_get_is_corrupted (loader)) + record_validity_seen (loader->corruption_reason); + return TRUE; } else @@ -1170,6 +1218,8 @@ _dbus_message_test (const char *test_data_dir) DBusMessageData mdata; int count; + reset_validities_seen (); + count = 0; _dbus_message_data_iter_init (&diter); @@ -1190,6 +1240,9 @@ _dbus_message_test (const char *test_data_dir) } printf ("%d sample messages tested\n", count); + + print_validities_seen (FALSE); + print_validities_seen (TRUE); } check_memleaks (); diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 46a30b6f..a2852558 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -2957,11 +2957,9 @@ _dbus_message_loader_new (void) loader->corrupted = FALSE; loader->corruption_reason = DBUS_VALID; - - /* Try to cap message size at something that won't *totally* hose - * the system if we have a couple of them. - */ - loader->max_message_size = _DBUS_ONE_MEGABYTE * 32; + + /* this can be configured by the app, but defaults to the protocol max */ + loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH; if (!_dbus_string_init (&loader->data)) { diff --git a/dbus/dbus-string-util.c b/dbus/dbus-string-util.c index 1ff2ec67..0610c66d 100644 --- a/dbus/dbus-string-util.c +++ b/dbus/dbus-string-util.c @@ -377,6 +377,49 @@ _dbus_string_test (void) ++i; } + /* Test equality */ + if (!_dbus_string_init (&str)) + _dbus_assert_not_reached ("oom"); + + if (!_dbus_string_append (&str, "Hello World")) + _dbus_assert_not_reached ("oom"); + + _dbus_string_init_const (&other, "H"); + _dbus_assert (_dbus_string_equal_substring (&str, 0, 1, &other, 0)); + _dbus_assert (_dbus_string_equal_substring (&str, 1, 0, &other, 1)); + _dbus_string_init_const (&other, "Hello"); + _dbus_assert (_dbus_string_equal_substring (&str, 0, 5, &other, 0)); + _dbus_assert (_dbus_string_equal_substring (&str, 1, 4, &other, 1)); + _dbus_assert (_dbus_string_equal_substring (&str, 2, 3, &other, 2)); + _dbus_assert (_dbus_string_equal_substring (&str, 3, 2, &other, 3)); + _dbus_assert (_dbus_string_equal_substring (&str, 4, 1, &other, 4)); + _dbus_assert (_dbus_string_equal_substring (&str, 5, 0, &other, 5)); + + _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 0)); + _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 1)); + _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 2)); + _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 3)); + _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 4)); + _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 5)); + + + _dbus_string_init_const (&other, "World"); + _dbus_assert (_dbus_string_equal_substring (&str, 6, 5, &other, 0)); + _dbus_assert (_dbus_string_equal_substring (&str, 7, 4, &other, 1)); + _dbus_assert (_dbus_string_equal_substring (&str, 8, 3, &other, 2)); + _dbus_assert (_dbus_string_equal_substring (&str, 9, 2, &other, 3)); + _dbus_assert (_dbus_string_equal_substring (&str, 10, 1, &other, 4)); + _dbus_assert (_dbus_string_equal_substring (&str, 11, 0, &other, 5)); + + _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 6)); + _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 7)); + _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 8)); + _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 9)); + _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 10)); + _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 11)); + + _dbus_string_free (&str); + /* Test appending data */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); |