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+2]; 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; } long_sig[i] = DBUS_TYPE_INVALID; 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+4]; 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; } long_sig[i] = DBUS_TYPE_INVALID; 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) { char byte_order; message = simple_method_call (); byte_order = _dbus_header_get_byte_order (&message->header); generate_from_message (data, expected_validity, message); _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET, DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4, byte_order); _dbus_marshal_set_uint32 (data, FIELDS_ARRAY_LENGTH_OFFSET, DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4, 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_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_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 if (item_seq == 15) { message = simple_error (); if (!dbus_message_set_error_name (message, NULL)) _dbus_assert_not_reached ("oom"); generate_from_message (data, expected_validity, message); *expected_validity = DBUS_INVALID_MISSING_ERROR_NAME; } else if (item_seq == 16) { char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*4+10]; const char *v_STRING; int i; int n_begins; 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*3 + 3)) { long_sig[i] = DBUS_TYPE_ARRAY; ++i; long_sig[i] = DBUS_DICT_ENTRY_BEGIN_CHAR; ++i; long_sig[i] = DBUS_TYPE_INT32; ++i; } n_begins = i / 3; long_sig[i] = DBUS_TYPE_INT32; ++i; while (n_begins > 0) { long_sig[i] = DBUS_DICT_ENTRY_END_CHAR; ++i; n_begins -= 1; } long_sig[i] = DBUS_TYPE_INVALID; 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_DICT_ENTRY_RECURSION; } else if (item_seq == 17) { 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_TYPE_ARRAY); _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR); *expected_validity = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED; } else if (item_seq == 18) { 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_DICT_ENTRY_END_CHAR); *expected_validity = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED; } else if (item_seq == 19) { 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_TYPE_ARRAY); _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR); _dbus_string_set_byte (data, pos + 3, DBUS_DICT_ENTRY_END_CHAR); *expected_validity = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS; } else if (item_seq == 20) { /* 64 levels of nesting is OK */ message = message_with_nesting_levels(64); generate_from_message (data, expected_validity, message); *expected_validity = DBUS_VALID; } else if (item_seq == 21) { /* 65 levels of nesting is not OK */ message = message_with_nesting_levels(65); generate_from_message (data, expected_validity, message); *expected_validity = DBUS_INVALID_NESTED_TOO_DEEPLY; } else { return FALSE; } if (message) dbus_message_unref (message); iter_next (iter); return TRUE; }
static DBusValidity load_and_validate_field (DBusHeader *header, int field, DBusTypeReader *variant_reader) { int type; 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, int start, int len); /* Supposed to have been checked already */ _dbus_assert (field <= DBUS_HEADER_FIELD_LAST); _dbus_assert (field != DBUS_HEADER_FIELD_INVALID); /* Before we can cache a field, we need to know it has the right type */ type = _dbus_type_reader_get_current_type (variant_reader); _dbus_assert (_dbus_header_field_types[field].code == field); expected_type = EXPECTED_TYPE_OF_FIELD (field); if (type != expected_type) { _dbus_verbose ("Field %d should have type %d but has %d\n", field, expected_type, type); return DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE; } /* If the field was provided twice, we aren't happy */ if (header->fields[field].value_pos >= 0) { _dbus_verbose ("Header field %d seen a second time\n", field); return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE; } /* Now we can cache and look at the field content */ _dbus_verbose ("initially caching field %d\n", field); _dbus_header_cache_one (header, field, variant_reader); string_validation_func = NULL; /* make compiler happy that all this is initialized */ v_UINT32 = 0; value_str = NULL; value_pos = -1; str_data_pos = -1; bad_string_code = DBUS_VALID; if (expected_type == DBUS_TYPE_UINT32) { _dbus_header_get_field_basic (header, field, expected_type, &v_UINT32); } else if (expected_type == DBUS_TYPE_STRING || expected_type == DBUS_TYPE_OBJECT_PATH || expected_type == DBUS_TYPE_SIGNATURE) { _dbus_header_get_field_raw (header, field, &value_str, &value_pos); str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4; } else { _dbus_assert_not_reached ("none of the known fields should have this type"); } switch (field) { case DBUS_HEADER_FIELD_DESTINATION: string_validation_func = _dbus_validate_bus_name; bad_string_code = DBUS_INVALID_BAD_DESTINATION; break; case DBUS_HEADER_FIELD_INTERFACE: string_validation_func = _dbus_validate_interface; bad_string_code = DBUS_INVALID_BAD_INTERFACE; if (_dbus_string_equal_substring (&_dbus_local_interface_str, 0, _dbus_string_get_length (&_dbus_local_interface_str), value_str, str_data_pos)) { _dbus_verbose ("Message is on the local interface\n"); return DBUS_INVALID_USES_LOCAL_INTERFACE; } break; case DBUS_HEADER_FIELD_MEMBER: string_validation_func = _dbus_validate_member; bad_string_code = DBUS_INVALID_BAD_MEMBER; break; case DBUS_HEADER_FIELD_ERROR_NAME: string_validation_func = _dbus_validate_error_name; bad_string_code = DBUS_INVALID_BAD_ERROR_NAME; break; case DBUS_HEADER_FIELD_SENDER: string_validation_func = _dbus_validate_bus_name; bad_string_code = DBUS_INVALID_BAD_SENDER; break; case DBUS_HEADER_FIELD_PATH: /* OBJECT_PATH was validated generically due to its type */ string_validation_func = NULL; if (_dbus_string_equal_substring (&_dbus_local_path_str, 0, _dbus_string_get_length (&_dbus_local_path_str), value_str, str_data_pos)) { _dbus_verbose ("Message is from the local path\n"); return DBUS_INVALID_USES_LOCAL_PATH; } break; case DBUS_HEADER_FIELD_REPLY_SERIAL: /* Can't be 0 */ if (v_UINT32 == 0) { return DBUS_INVALID_BAD_SERIAL; } break; case DBUS_HEADER_FIELD_SIGNATURE: /* SIGNATURE validated generically due to its type */ string_validation_func = NULL; break; default: _dbus_assert_not_reached ("unknown field shouldn't be seen here"); break; } if (string_validation_func) { dbus_uint32_t len; _dbus_assert (bad_string_code != DBUS_VALID); len = _dbus_marshal_read_uint32 (value_str, value_pos, header->byte_order, NULL); #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; } return DBUS_VALID; }