/** * Generates the given number of random bytes, where the bytes are * chosen from the alphanumeric ASCII subset. * * @param str the string * @param n_bytes the number of random ASCII bytes to append to string * @param error location to store reason for failure * @returns #TRUE on success, #FALSE if no memory or other failure */ dbus_bool_t _dbus_generate_random_ascii (DBusString *str, int n_bytes, DBusError *error) { static const char letters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; int i; int len; if (!_dbus_generate_random_bytes (str, n_bytes, error)) return FALSE; len = _dbus_string_get_length (str); i = len - n_bytes; while (i < len) { _dbus_string_set_byte (str, i, letters[_dbus_string_get_byte (str, i) % (sizeof (letters) - 1)]); ++i; } _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes, n_bytes)); return TRUE; }
dbus_bool_t _dbus_path_is_absolute (const DBusString *filename) { if (_dbus_string_get_length (filename) > 0) return _dbus_string_get_byte (filename, 0) == '/'; else return FALSE; }
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 dbus_bool_t parse_section_start (BusDesktopFileParser *parser, DBusError *error) { int line_end, eol_len; char *section_name; _DBUS_ASSERT_ERROR_IS_CLEAR (error); if (!_dbus_string_find_eol (&parser->data, parser->pos, &line_end, &eol_len)) line_end = parser->len; if (line_end - parser->pos <= 2 || _dbus_string_get_byte (&parser->data, line_end - 1) != ']') { report_error (parser, "Invalid syntax for section header", BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error); parser_free (parser); return FALSE; } section_name = unescape_string (parser, &parser->data, parser->pos + 1, line_end - 1, error); if (section_name == NULL) { parser_free (parser); return FALSE; } if (!is_valid_section_name (section_name)) { report_error (parser, "Invalid characters in section name", BUS_DESKTOP_PARSE_ERROR_INVALID_CHARS, error); parser_free (parser); dbus_free (section_name); return FALSE; } if (open_section (parser, section_name) == NULL) { dbus_free (section_name); parser_free (parser); BUS_SET_OOM (error); return FALSE; } if (line_end == parser->len) parser->pos = parser->len; else parser->pos = line_end + eol_len; parser->line_num += 1; dbus_free (section_name); return TRUE; }
/** * Gets the type of the message. * * @param header the header * @returns the type */ int _dbus_header_get_message_type (DBusHeader *header) { int type; type = _dbus_string_get_byte (&header->data, TYPE_OFFSET); _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID); return type; }
dbus_bool_t _dbus_string_get_dirname (const DBusString *filename, DBusString *dirname) { int sep; _dbus_assert (filename != dirname); _dbus_assert (filename != NULL); _dbus_assert (dirname != NULL); /* Ignore any separators on the end */ sep = _dbus_string_get_length (filename); if (sep == 0) return _dbus_string_append (dirname, "."); /* empty string passed in */ while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/') --sep; _dbus_assert (sep >= 0); if (sep == 0) return _dbus_string_append (dirname, "/"); /* Now find the previous separator */ _dbus_string_find_byte_backward (filename, sep, '/', &sep); if (sep < 0) return _dbus_string_append (dirname, "."); /* skip multiple separators */ while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/') --sep; _dbus_assert (sep >= 0); if (sep == 0 && _dbus_string_get_byte (filename, 0) == '/') return _dbus_string_append (dirname, "/"); else return _dbus_string_copy_len (filename, 0, sep - 0, dirname, _dbus_string_get_length (dirname)); }
static dbus_bool_t is_blank_line (BusDesktopFileParser *parser) { int p; char c; p = parser->pos; c = _dbus_string_get_byte (&parser->data, p); while (c && c != '\n') { if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f')) return FALSE; p++; c = _dbus_string_get_byte (&parser->data, p); } return TRUE; }
static dbus_bool_t generate_byte_changed (DBusMessageDataIter *iter, DBusString *data, DBusValidity *expected_validity) { int byte_seq; int v_BYTE; /* This is a little convoluted to make the bodies the * outer loop and each byte of each body the inner * loop */ restart: if (!generate_many_bodies (iter, data, expected_validity)) return FALSE; iter_recurse (iter); byte_seq = iter_get_sequence (iter); iter_next (iter); iter_unrecurse (iter); if (byte_seq == _dbus_string_get_length (data)) { _dbus_string_set_length (data, 0); /* reset byte count */ iter_recurse (iter); iter_set_sequence (iter, 0); iter_unrecurse (iter); goto restart; } else { /* Undo the "next" in generate_many_bodies */ iter_set_sequence (iter, iter_get_sequence (iter) - 1); } _dbus_assert (byte_seq < _dbus_string_get_length (data)); v_BYTE = _dbus_string_get_byte (data, byte_seq); v_BYTE += byte_seq; /* arbitrary but deterministic change to the byte */ _dbus_string_set_byte (data, byte_seq, v_BYTE); *expected_validity = DBUS_VALIDITY_UNKNOWN; return TRUE; }
static void randomly_change_one_type (const DBusString *orig_data, DBusString *mutated) { int i; int len; if (orig_data != mutated) { _dbus_string_set_length (mutated, 0); if (!_dbus_string_copy (orig_data, 0, mutated, 0)) _dbus_assert_not_reached ("out of mem"); } if (_dbus_string_get_length (mutated) == 0) return; len = _dbus_string_get_length (mutated); i = random_int_in_range (0, len); /* Look for a type starting at a random location, * and replace with a different type */ while (i < len) { int b; b = _dbus_string_get_byte (mutated, i); if (dbus_type_is_valid (b)) { _dbus_string_set_byte (mutated, i, random_type ()); return; } ++i; } }
/** * Tries loading the given message data. * * * @param data the message data * @param expected_validity what the message has to be like to return #TRUE * @returns #TRUE if the message has the expected validity */ dbus_bool_t dbus_internal_do_not_use_try_message_data (const DBusString *data, DBusValidity expected_validity) { DBusMessageLoader *loader; dbus_bool_t retval; int len; int i; loader = NULL; retval = FALSE; /* Write the data one byte at a time */ loader = _dbus_message_loader_new (); /* check some trivial loader functions */ _dbus_message_loader_ref (loader); _dbus_message_loader_unref (loader); _dbus_message_loader_get_max_message_size (loader); len = _dbus_string_get_length (data); for (i = 0; i < len; i++) { DBusString *buffer; _dbus_message_loader_get_buffer (loader, &buffer); _dbus_string_append_byte (buffer, _dbus_string_get_byte (data, i)); _dbus_message_loader_return_buffer (loader, buffer, 1); } if (!check_loader_results (loader, expected_validity)) goto failed; _dbus_message_loader_unref (loader); loader = NULL; /* Write the data all at once */ loader = _dbus_message_loader_new (); { DBusString *buffer; _dbus_message_loader_get_buffer (loader, &buffer); _dbus_string_copy (data, 0, buffer, _dbus_string_get_length (buffer)); _dbus_message_loader_return_buffer (loader, buffer, 1); } if (!check_loader_results (loader, expected_validity)) goto failed; _dbus_message_loader_unref (loader); loader = NULL; /* Write the data 2 bytes at a time */ loader = _dbus_message_loader_new (); len = _dbus_string_get_length (data); for (i = 0; i < len; i += 2) { DBusString *buffer; _dbus_message_loader_get_buffer (loader, &buffer); _dbus_string_append_byte (buffer, _dbus_string_get_byte (data, i)); if ((i+1) < len) _dbus_string_append_byte (buffer, _dbus_string_get_byte (data, i+1)); _dbus_message_loader_return_buffer (loader, buffer, 1); } if (!check_loader_results (loader, expected_validity)) goto failed; _dbus_message_loader_unref (loader); loader = NULL; retval = TRUE; failed: if (loader) _dbus_message_loader_unref (loader); return retval; }
dbus_bool_t bus_registry_release_service (BusRegistry *registry, DBusConnection *connection, const DBusString *service_name, dbus_uint32_t *result, BusTransaction *transaction, DBusError *error) { dbus_bool_t retval; BusService *service; retval = FALSE; if (!_dbus_validate_bus_name (service_name, 0, _dbus_string_get_length (service_name))) { dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Given bus name \"%s\" is not valid", _dbus_string_get_const_data (service_name)); _dbus_verbose ("Attempt to release invalid service name\n"); goto out; } if (_dbus_string_get_byte (service_name, 0) == ':') { /* Not allowed; the base service name cannot be created or released */ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Cannot release a service starting with ':' such as \"%s\"", _dbus_string_get_const_data (service_name)); _dbus_verbose ("Attempt to release invalid base service name \"%s\"", _dbus_string_get_const_data (service_name)); goto out; } if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS)) { /* Not allowed; the base service name cannot be created or released */ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Cannot release the %s service because it is owned by the bus", DBUS_SERVICE_DBUS); _dbus_verbose ("Attempt to release service name \"%s\"", DBUS_SERVICE_DBUS); goto out; } service = bus_registry_lookup (registry, service_name); if (service == NULL) { *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT; } else if (!bus_service_has_owner (service, connection)) { *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER; } else { if (!bus_service_remove_owner (service, connection, transaction, error)) goto out; _dbus_assert (!bus_service_has_owner (service, connection)); *result = DBUS_RELEASE_NAME_REPLY_RELEASED; } retval = TRUE; out: return retval; }
dbus_bool_t bus_registry_acquire_service (BusRegistry *registry, DBusConnection *connection, const DBusString *service_name, dbus_uint32_t flags, dbus_uint32_t *result, BusTransaction *transaction, DBusError *error) { dbus_bool_t retval; DBusConnection *old_owner_conn; BusClientPolicy *policy; BusService *service; BusActivation *activation; BusSELinuxID *sid; BusOwner *primary_owner; retval = FALSE; if (!_dbus_validate_bus_name (service_name, 0, _dbus_string_get_length (service_name))) { dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Requested bus name \"%s\" is not valid", _dbus_string_get_const_data (service_name)); _dbus_verbose ("Attempt to acquire invalid service name\n"); goto out; } if (_dbus_string_get_byte (service_name, 0) == ':') { /* Not allowed; only base services can start with ':' */ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Cannot acquire a service starting with ':' such as \"%s\"", _dbus_string_get_const_data (service_name)); _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"", _dbus_string_get_const_data (service_name)); goto out; } if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS)) { dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Connection \"%s\" is not allowed to own the service \"%s\"because " "it is reserved for D-Bus' use only", bus_connection_is_active (connection) ? bus_connection_get_name (connection) : "(inactive)", DBUS_SERVICE_DBUS); goto out; } policy = bus_connection_get_policy (connection); _dbus_assert (policy != NULL); /* Note that if sid is #NULL then the bus's own context gets used * in bus_connection_selinux_allows_acquire_service() */ sid = bus_selinux_id_table_lookup (registry->service_sid_table, service_name); if (!bus_selinux_allows_acquire_service (connection, sid, _dbus_string_get_const_data (service_name), error)) { if (dbus_error_is_set (error) && dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY)) { goto out; } dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, "Connection \"%s\" is not allowed to own the service \"%s\" due " "to SELinux policy", bus_connection_is_active (connection) ? bus_connection_get_name (connection) : "(inactive)", _dbus_string_get_const_data (service_name)); goto out; } if (!bus_client_policy_check_can_own (policy, service_name)) { dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, "Connection \"%s\" is not allowed to own the service \"%s\" due " "to security policies in the configuration file", bus_connection_is_active (connection) ? bus_connection_get_name (connection) : "(inactive)", _dbus_string_get_const_data (service_name)); goto out; } if (bus_connection_get_n_services_owned (connection) >= bus_context_get_max_services_per_connection (registry->context)) { dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, "Connection \"%s\" is not allowed to own more services " "(increase limits in configuration file if required)", bus_connection_is_active (connection) ? bus_connection_get_name (connection) : "(inactive)"); goto out; } service = bus_registry_lookup (registry, service_name); if (service != NULL) { primary_owner = bus_service_get_primary_owner (service); if (primary_owner != NULL) old_owner_conn = primary_owner->conn; else old_owner_conn = NULL; } else old_owner_conn = NULL; if (service == NULL) { service = bus_registry_ensure (registry, service_name, connection, flags, transaction, error); if (service == NULL) goto out; } primary_owner = bus_service_get_primary_owner (service); if (primary_owner == NULL) goto out; if (old_owner_conn == NULL) { _dbus_assert (primary_owner->conn == connection); *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER; } else if (old_owner_conn == connection) { bus_owner_set_flags (primary_owner, flags); *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER; } else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) && !(bus_service_get_allow_replacement (service))) || ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) && !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING))) { DBusList *link; BusOwner *temp_owner; /* Since we can't be queued if we are already in the queue remove us */ link = _bus_service_find_owner_link (service, connection); if (link != NULL) { _dbus_list_unlink (&service->owners, link); temp_owner = (BusOwner *)link->data; bus_owner_unref (temp_owner); _dbus_list_free_link (link); } *result = DBUS_REQUEST_NAME_REPLY_EXISTS; } else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) && (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || !(bus_service_get_allow_replacement (service)))) { /* Queue the connection */ if (!bus_service_add_owner (service, connection, flags, transaction, error)) goto out; *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE; } else { /* Replace the current owner */ /* We enqueue the new owner and remove the first one because * that will cause NameAcquired and NameLost messages to * be sent. */ if (!bus_service_add_owner (service, connection, flags, transaction, error)) goto out; if (primary_owner->do_not_queue) { if (!bus_service_remove_owner (service, old_owner_conn, transaction, error)) goto out; } else { if (!bus_service_swap_owner (service, old_owner_conn, transaction, error)) goto out; } _dbus_assert (connection == bus_service_get_primary_owner (service)->conn); *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER; } activation = bus_context_get_activation (registry->context); retval = bus_activation_send_pending_auto_activation_messages (activation, service, transaction); if (!retval) BUS_SET_OOM (error); out: return retval; }
/** * Given data long enough to contain the length of the message body * and the fields array, check whether the data is long enough to * contain the entire message (assuming the claimed lengths are * accurate). Also checks that the lengths are in sanity parameters. * * @param max_message_length maximum length of a valid message * @param validity return location for why the data is invalid if it is * @param byte_order return location for byte order * @param fields_array_len return location for claimed fields array length * @param header_len return location for claimed header length * @param body_len return location for claimed body length * @param str the data * @param start start of data, 8-aligned * @param len length of data * @returns #TRUE if the data is long enough for the claimed length, and the lengths were valid */ dbus_bool_t _dbus_header_have_message_untrusted (int max_message_length, DBusValidity *validity, int *byte_order, int *fields_array_len, int *header_len, int *body_len, const DBusString *str, int start, int len) { dbus_uint32_t header_len_unsigned; dbus_uint32_t fields_array_len_unsigned; dbus_uint32_t body_len_unsigned; _dbus_assert (start >= 0); _dbus_assert (start < _DBUS_INT32_MAX / 2); _dbus_assert (len >= 0); _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8)); *byte_order = _dbus_string_get_byte (str, start + BYTE_ORDER_OFFSET); if (*byte_order != DBUS_LITTLE_ENDIAN && *byte_order != DBUS_BIG_ENDIAN) { *validity = DBUS_INVALID_BAD_BYTE_ORDER; return FALSE; } _dbus_assert (FIELDS_ARRAY_LENGTH_OFFSET + 4 <= len); fields_array_len_unsigned = _dbus_marshal_read_uint32 (str, start + FIELDS_ARRAY_LENGTH_OFFSET, *byte_order, NULL); if (fields_array_len_unsigned > (unsigned) max_message_length) { *validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH; return FALSE; } _dbus_assert (BODY_LENGTH_OFFSET + 4 < len); body_len_unsigned = _dbus_marshal_read_uint32 (str, start + BODY_LENGTH_OFFSET, *byte_order, NULL); if (body_len_unsigned > (unsigned) max_message_length) { *validity = DBUS_INVALID_INSANE_BODY_LENGTH; return FALSE; } header_len_unsigned = FIRST_FIELD_OFFSET + fields_array_len_unsigned; header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8); /* overflow should be impossible since the lengths aren't allowed to * be huge. */ _dbus_assert (max_message_length < _DBUS_INT32_MAX / 2); if (body_len_unsigned + header_len_unsigned > (unsigned) max_message_length) { *validity = DBUS_INVALID_MESSAGE_TOO_LONG; return FALSE; } _dbus_assert (body_len_unsigned < (unsigned) _DBUS_INT32_MAX); _dbus_assert (fields_array_len_unsigned < (unsigned) _DBUS_INT32_MAX); _dbus_assert (header_len_unsigned < (unsigned) _DBUS_INT32_MAX); *body_len = body_len_unsigned; *fields_array_len = fields_array_len_unsigned; *header_len = header_len_unsigned; *validity = DBUS_VALID; _dbus_verbose ("have %d bytes, need body %u + header %u = %u\n", len, body_len_unsigned, header_len_unsigned, body_len_unsigned + header_len_unsigned); return (body_len_unsigned + header_len_unsigned) <= (unsigned) len; }
static dbus_bool_t generate_wrong_length (DBusMessageDataIter *iter, DBusString *data, DBusValidity *expected_validity) { int lengths[] = { -42, -17, -16, -15, -9, -8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 30 }; int adjust; int len_seq; restart: len_seq = iter_get_sequence (iter); if (len_seq == _DBUS_N_ELEMENTS (lengths)) return FALSE; _dbus_assert (len_seq < _DBUS_N_ELEMENTS (lengths)); iter_recurse (iter); if (!generate_many_bodies (iter, data, expected_validity)) { iter_set_sequence (iter, 0); /* reset to first body */ iter_unrecurse (iter); iter_next (iter); /* next length adjustment */ goto restart; } iter_unrecurse (iter); adjust = lengths[len_seq]; if (adjust < 0) { if ((_dbus_string_get_length (data) + adjust) < DBUS_MINIMUM_HEADER_SIZE) _dbus_string_set_length (data, DBUS_MINIMUM_HEADER_SIZE); else _dbus_string_shorten (data, - adjust); *expected_validity = DBUS_INVALID_FOR_UNKNOWN_REASON; } else { if (!_dbus_string_lengthen (data, adjust)) _dbus_assert_not_reached ("oom"); *expected_validity = DBUS_INVALID_TOO_MUCH_DATA; } /* Fixup lengths */ { int old_body_len; int new_body_len; int byte_order; _dbus_assert (_dbus_string_get_length (data) >= DBUS_MINIMUM_HEADER_SIZE); byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET); old_body_len = _dbus_marshal_read_uint32 (data, BODY_LENGTH_OFFSET, byte_order, NULL); _dbus_assert (old_body_len < _dbus_string_get_length (data)); new_body_len = old_body_len + adjust; if (new_body_len < 0) { new_body_len = 0; /* we just munged the header, and aren't sure how */ *expected_validity = DBUS_VALIDITY_UNKNOWN; } _dbus_verbose ("changing body len from %u to %u by adjust %d\n", old_body_len, new_body_len, adjust); _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET, new_body_len, byte_order); } return TRUE; }
static dbus_bool_t generate_uint32_changed (DBusMessageDataIter *iter, DBusString *data, DBusValidity *expected_validity) { int body_seq; int byte_seq; int change_seq; dbus_uint32_t v_UINT32; int byte_order; const UIntChange *change; int base_depth; /* Outer loop is each body, next loop is each change, * inner loop is each change location */ base_depth = iter->depth; next_body: _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; _dbus_assert (iter->depth == (base_depth + 0)); iter_set_sequence (iter, body_seq); /* undo the "next" from generate_many_bodies */ iter_recurse (iter); next_change: _dbus_assert (iter->depth == (base_depth + 1)); change_seq = iter_get_sequence (iter); if (change_seq == _DBUS_N_ELEMENTS (uint32_changes)) { /* Reset change count */ iter_set_sequence (iter, 0); iter_unrecurse (iter); iter_next (iter); goto next_body; } _dbus_assert (iter->depth == (base_depth + 1)); iter_recurse (iter); _dbus_assert (iter->depth == (base_depth + 2)); byte_seq = iter_get_sequence (iter); /* skip 4 bytes at a time */ iter_next (iter); iter_next (iter); iter_next (iter); iter_next (iter); iter_unrecurse (iter); _dbus_assert (_DBUS_ALIGN_VALUE (byte_seq, 4) == (unsigned) byte_seq); if (byte_seq >= (_dbus_string_get_length (data) - 4)) { /* reset byte count */ _dbus_assert (iter->depth == (base_depth + 1)); iter_recurse (iter); _dbus_assert (iter->depth == (base_depth + 2)); iter_set_sequence (iter, 0); iter_unrecurse (iter); _dbus_assert (iter->depth == (base_depth + 1)); iter_next (iter); goto next_change; } _dbus_assert (byte_seq <= (_dbus_string_get_length (data) - 4)); byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET); v_UINT32 = _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL); change = &uint32_changes[change_seq]; if (change->type == CHANGE_TYPE_ADJUST) { v_UINT32 += (int) change->value; } else { v_UINT32 = change->value; } #if 0 printf ("body %d change %d pos %d ", body_seq, change_seq, byte_seq); if (change->type == CHANGE_TYPE_ADJUST) printf ("adjust by %d", (int) change->value); else printf ("set to %u", change->value); printf (" \t%u -> %u\n", _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL), v_UINT32); #endif _dbus_marshal_set_uint32 (data, byte_seq, v_UINT32, byte_order); *expected_validity = DBUS_VALIDITY_UNKNOWN; _dbus_assert (iter->depth == (base_depth + 1)); iter_unrecurse (iter); _dbus_assert (iter->depth == (base_depth + 0)); return TRUE; }
/* this is slightly different from the other append_quoted_string * in dbus-message-builder.c */ static dbus_bool_t append_quoted_string (DBusString *dest, const DBusString *quoted) { dbus_bool_t in_quotes = FALSE; dbus_bool_t in_backslash = FALSE; int i; i = 0; while (i < _dbus_string_get_length (quoted)) { unsigned char b; b = _dbus_string_get_byte (quoted, i); if (in_backslash) { unsigned char a; if (b == 'r') a = '\r'; else if (b == 'n') a = '\n'; else if (b == '\\') a = '\\'; else { _dbus_warn ("bad backslashed byte %c\n", b); return FALSE; } if (!_dbus_string_append_byte (dest, a)) return FALSE; in_backslash = FALSE; } else if (b == '\\') { in_backslash = TRUE; } else if (in_quotes) { if (b == '\'') in_quotes = FALSE; else { if (!_dbus_string_append_byte (dest, b)) return FALSE; } } else { if (b == '\'') in_quotes = TRUE; else if (b == ' ' || b == '\n' || b == '\t') break; /* end on whitespace if not quoted */ else { if (!_dbus_string_append_byte (dest, b)) return FALSE; } } ++i; } return TRUE; }
BusDesktopFile* bus_desktop_file_load (DBusString *filename, DBusError *error) { DBusString str; BusDesktopFileParser parser; DBusStat sb; _DBUS_ASSERT_ERROR_IS_CLEAR (error); /* Clearly there's a race here, but it's just to make it unlikely * that we do something silly, we still handle doing it below. */ if (!_dbus_stat (filename, &sb, error)) return NULL; if (sb.size > _DBUS_ONE_KILOBYTE * 128) { dbus_set_error (error, DBUS_ERROR_FAILED, "Desktop file size (%ld bytes) is too large", (long) sb.size); return NULL; } if (!_dbus_string_init (&str)) return NULL; if (!_dbus_file_get_contents (&str, filename, error)) { _dbus_string_free (&str); return NULL; } if (!_dbus_string_validate_utf8 (&str, 0, _dbus_string_get_length (&str))) { _dbus_string_free (&str); dbus_set_error (error, DBUS_ERROR_FAILED, "invalid UTF-8"); return NULL; } parser.desktop_file = dbus_new0 (BusDesktopFile, 1); if (parser.desktop_file == NULL) { _dbus_string_free (&str); BUS_SET_OOM (error); return NULL; } parser.data = str; parser.line_num = 1; parser.pos = 0; parser.len = _dbus_string_get_length (&parser.data); parser.current_section = -1; while (parser.pos < parser.len) { if (_dbus_string_get_byte (&parser.data, parser.pos) == '[') { if (!parse_section_start (&parser, error)) { return NULL; } } else if (is_blank_line (&parser) || _dbus_string_get_byte (&parser.data, parser.pos) == '#') parse_comment_or_blank (&parser); else { if (!parse_key_value (&parser, error)) { return NULL; } } } _dbus_string_free (&parser.data); return parser.desktop_file; }
static dbus_bool_t parse_key_value (BusDesktopFileParser *parser, DBusError *error) { int line_end; int key_start, key_end; int value_start; int p; char *value, *tmp; DBusString key; BusDesktopFileLine *line; _DBUS_ASSERT_ERROR_IS_CLEAR (error); if (!_dbus_string_find (&parser->data, parser->pos, "\n", &line_end)) line_end = parser->len; p = parser->pos; key_start = p; while (p < line_end && (valid[_dbus_string_get_byte (&parser->data, p)] & VALID_KEY_CHAR)) p++; key_end = p; if (key_start == key_end) { report_error (parser, "Empty key name", BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error); parser_free (parser); return FALSE; } /* We ignore locales for now */ if (p < line_end && _dbus_string_get_byte (&parser->data, p) == '[') { if (line_end == parser->len) parser->pos = parser->len; else parser->pos = line_end + 1; parser->line_num += 1; return TRUE; } /* Skip space before '=' */ while (p < line_end && _dbus_string_get_byte (&parser->data, p) == ' ') p++; if (p < line_end && _dbus_string_get_byte (&parser->data, p) != '=') { report_error (parser, "Invalid characters in key name", BUS_DESKTOP_PARSE_ERROR_INVALID_CHARS, error); parser_free (parser); return FALSE; } if (p == line_end) { report_error (parser, "No '=' in key/value pair", BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error); parser_free (parser); return FALSE; } /* Skip the '=' */ p++; /* Skip space after '=' */ while (p < line_end && _dbus_string_get_byte (&parser->data, p) == ' ') p++; value_start = p; value = unescape_string (parser, &parser->data, value_start, line_end, error); if (value == NULL) { parser_free (parser); return FALSE; } line = new_line (parser); if (line == NULL) { parser_free (parser); return FALSE; } if (!_dbus_string_init (&key)) { parser_free (parser); return FALSE; } if (!_dbus_string_copy_len (&parser->data, key_start, key_end - key_start, &key, 0)) { parser_free (parser); return FALSE; } if (!_dbus_string_steal_data (&key, &tmp)) { parser_free (parser); return FALSE; } _dbus_string_free (&key); line->key = tmp; line->value = value; if (line_end == parser->len) parser->pos = parser->len; else parser->pos = line_end + 1; parser->line_num += 1; return TRUE; }
static char * unescape_string (BusDesktopFileParser *parser, const DBusString *str, int pos, int end_pos, DBusError *error) { char *retval, *q; _DBUS_ASSERT_ERROR_IS_CLEAR (error); /* len + 1 is enough, because unescaping never makes the * string longer */ retval = dbus_malloc (end_pos - pos + 1); if (retval == NULL) { BUS_SET_OOM (error); return NULL; } q = retval; while (pos < end_pos) { if (_dbus_string_get_byte (str, pos) == 0) { /* Found an embedded null */ dbus_free (retval); report_error (parser, "Text to be unescaped contains embedded nul", BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error); return NULL; } if (_dbus_string_get_byte (str, pos) == '\\') { pos ++; if (pos >= end_pos) { /* Escape at end of string */ dbus_free (retval); report_error (parser, "Text to be unescaped ended in \\", BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error); return NULL; } switch (_dbus_string_get_byte (str, pos)) { case 's': *q++ = ' '; break; case 't': *q++ = '\t'; break; case 'n': *q++ = '\n'; break; case 'r': *q++ = '\r'; break; case '\\': *q++ = '\\'; break; default: /* Invalid escape code */ dbus_free (retval); report_error (parser, "Text to be unescaped had invalid escape sequence", BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error); return NULL; } pos++; } else { *q++ =_dbus_string_get_byte (str, pos); pos++; } } *q = 0; return retval; }
/** * @ingroup DBusStringInternals * Unit test for DBusString. * * @todo Need to write tests for _dbus_string_copy() and * _dbus_string_move() moving to/from each of start/middle/end of a * string. Also need tests for _dbus_string_move_len () * * @returns #TRUE on success. */ dbus_bool_t _dbus_string_test (void) { DBusString str; DBusString other; int i, end; long v; double d; int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 }; char *s; dbus_unichar_t ch; i = 0; while (i < _DBUS_N_ELEMENTS (lens)) { if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); set_max_length (&str, lens[i]); test_max_len (&str, lens[i]); _dbus_string_free (&str); ++i; } /* Test shortening and setting length */ i = 0; while (i < _DBUS_N_ELEMENTS (lens)) { int j; if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); set_max_length (&str, lens[i]); if (!_dbus_string_set_length (&str, lens[i])) _dbus_assert_not_reached ("failed to set string length"); j = lens[i]; while (j > 0) { _dbus_assert (_dbus_string_get_length (&str) == j); if (j > 0) { _dbus_string_shorten (&str, 1); _dbus_assert (_dbus_string_get_length (&str) == (j - 1)); } --j; } _dbus_string_free (&str); ++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"); i = 0; while (i < 10) { if (!_dbus_string_append (&str, "a")) _dbus_assert_not_reached ("failed to append string to string\n"); _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1); if (!_dbus_string_append_byte (&str, 'b')) _dbus_assert_not_reached ("failed to append byte to string\n"); _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2); ++i; } _dbus_string_free (&str); /* Check steal_data */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("could not append to string"); i = _dbus_string_get_length (&str); if (!_dbus_string_steal_data (&str, &s)) _dbus_assert_not_reached ("failed to steal data"); _dbus_assert (_dbus_string_get_length (&str) == 0); _dbus_assert (((int)strlen (s)) == i); dbus_free (s); /* Check move */ if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("could not append to string"); i = _dbus_string_get_length (&str); if (!_dbus_string_init (&other)) _dbus_assert_not_reached ("could not init string"); if (!_dbus_string_move (&str, 0, &other, 0)) _dbus_assert_not_reached ("could not move"); _dbus_assert (_dbus_string_get_length (&str) == 0); _dbus_assert (_dbus_string_get_length (&other) == i); if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("could not append to string"); if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other))) _dbus_assert_not_reached ("could not move"); _dbus_assert (_dbus_string_get_length (&str) == 0); _dbus_assert (_dbus_string_get_length (&other) == i * 2); if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("could not append to string"); if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2)) _dbus_assert_not_reached ("could not move"); _dbus_assert (_dbus_string_get_length (&str) == 0); _dbus_assert (_dbus_string_get_length (&other) == i * 3); _dbus_string_free (&other); /* Check copy */ if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("could not append to string"); i = _dbus_string_get_length (&str); if (!_dbus_string_init (&other)) _dbus_assert_not_reached ("could not init string"); if (!_dbus_string_copy (&str, 0, &other, 0)) _dbus_assert_not_reached ("could not copy"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == i); if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other))) _dbus_assert_not_reached ("could not copy"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == i * 2); _dbus_assert (_dbus_string_equal_c_str (&other, "Hello WorldHello World")); if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2)) _dbus_assert_not_reached ("could not copy"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == i * 3); _dbus_assert (_dbus_string_equal_c_str (&other, "Hello WorldHello WorldHello World")); _dbus_string_free (&str); _dbus_string_free (&other); /* Check replace */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); if (!_dbus_string_append (&str, "Hello World")) _dbus_assert_not_reached ("could not append to string"); i = _dbus_string_get_length (&str); if (!_dbus_string_init (&other)) _dbus_assert_not_reached ("could not init string"); if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str), &other, 0, _dbus_string_get_length (&other))) _dbus_assert_not_reached ("could not replace"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == i); _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World")); if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str), &other, 5, 1)) _dbus_assert_not_reached ("could not replace center space"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1); _dbus_assert (_dbus_string_equal_c_str (&other, "HelloHello WorldWorld")); if (!_dbus_string_replace_len (&str, 1, 1, &other, _dbus_string_get_length (&other) - 1, 1)) _dbus_assert_not_reached ("could not replace end character"); _dbus_assert (_dbus_string_get_length (&str) == i); _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1); _dbus_assert (_dbus_string_equal_c_str (&other, "HelloHello WorldWorle")); _dbus_string_free (&str); _dbus_string_free (&other); /* Check append/get unichar */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); ch = 0; if (!_dbus_string_append_unichar (&str, 0xfffc)) _dbus_assert_not_reached ("failed to append unichar"); _dbus_string_get_unichar (&str, 0, &ch, &i); _dbus_assert (ch == 0xfffc); _dbus_assert (i == _dbus_string_get_length (&str)); _dbus_string_free (&str); /* Check insert/set/get byte */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); if (!_dbus_string_append (&str, "Hello")) _dbus_assert_not_reached ("failed to append Hello"); _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H'); _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e'); _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l'); _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l'); _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o'); _dbus_string_set_byte (&str, 1, 'q'); _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q'); if (!_dbus_string_insert_bytes (&str, 0, 1, 255)) _dbus_assert_not_reached ("can't insert byte"); if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z')) _dbus_assert_not_reached ("can't insert byte"); if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W')) _dbus_assert_not_reached ("can't insert byte"); _dbus_assert (_dbus_string_get_byte (&str, 0) == 255); _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H'); _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z'); _dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z'); _dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z'); _dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z'); _dbus_assert (_dbus_string_get_byte (&str, 6) == 'q'); _dbus_assert (_dbus_string_get_byte (&str, 7) == 'l'); _dbus_assert (_dbus_string_get_byte (&str, 8) == 'l'); _dbus_assert (_dbus_string_get_byte (&str, 9) == 'o'); _dbus_assert (_dbus_string_get_byte (&str, 10) == 'W'); _dbus_string_free (&str); /* Check append/parse int/double */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); if (!_dbus_string_append_int (&str, 27)) _dbus_assert_not_reached ("failed to append int"); i = _dbus_string_get_length (&str); if (!_dbus_string_parse_int (&str, 0, &v, &end)) _dbus_assert_not_reached ("failed to parse int"); _dbus_assert (v == 27); _dbus_assert (end == i); _dbus_string_free (&str); if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); if (!_dbus_string_append_double (&str, 50.3)) _dbus_assert_not_reached ("failed to append float"); i = _dbus_string_get_length (&str); if (!_dbus_string_parse_double (&str, 0, &d, &end)) _dbus_assert_not_reached ("failed to parse float"); _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6)); _dbus_assert (end == i); _dbus_string_free (&str); /* Test find */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("failed to init string"); if (!_dbus_string_append (&str, "Hello")) _dbus_assert_not_reached ("couldn't append to string"); if (!_dbus_string_find (&str, 0, "He", &i)) _dbus_assert_not_reached ("didn't find 'He'"); _dbus_assert (i == 0); if (!_dbus_string_find (&str, 0, "Hello", &i)) _dbus_assert_not_reached ("didn't find 'Hello'"); _dbus_assert (i == 0); if (!_dbus_string_find (&str, 0, "ello", &i)) _dbus_assert_not_reached ("didn't find 'ello'"); _dbus_assert (i == 1); if (!_dbus_string_find (&str, 0, "lo", &i)) _dbus_assert_not_reached ("didn't find 'lo'"); _dbus_assert (i == 3); if (!_dbus_string_find (&str, 2, "lo", &i)) _dbus_assert_not_reached ("didn't find 'lo'"); _dbus_assert (i == 3); if (_dbus_string_find (&str, 4, "lo", &i)) _dbus_assert_not_reached ("did find 'lo'"); if (!_dbus_string_find (&str, 0, "l", &i)) _dbus_assert_not_reached ("didn't find 'l'"); _dbus_assert (i == 2); if (!_dbus_string_find (&str, 0, "H", &i)) _dbus_assert_not_reached ("didn't find 'H'"); _dbus_assert (i == 0); if (!_dbus_string_find (&str, 0, "", &i)) _dbus_assert_not_reached ("didn't find ''"); _dbus_assert (i == 0); if (_dbus_string_find (&str, 0, "Hello!", NULL)) _dbus_assert_not_reached ("Did find 'Hello!'"); if (_dbus_string_find (&str, 0, "Oh, Hello", NULL)) _dbus_assert_not_reached ("Did find 'Oh, Hello'"); if (_dbus_string_find (&str, 0, "ill", NULL)) _dbus_assert_not_reached ("Did find 'ill'"); if (_dbus_string_find (&str, 0, "q", NULL)) _dbus_assert_not_reached ("Did find 'q'"); if (!_dbus_string_find_to (&str, 0, 2, "He", NULL)) _dbus_assert_not_reached ("Didn't find 'He'"); if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL)) _dbus_assert_not_reached ("Did find 'Hello'"); if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i)) _dbus_assert_not_reached ("Did not find 'H'"); _dbus_assert (i == 0); if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i)) _dbus_assert_not_reached ("Did not find 'o'"); _dbus_assert (i == _dbus_string_get_length (&str) - 1); if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i)) _dbus_assert_not_reached ("Did find 'o'"); _dbus_assert (i == -1); if (_dbus_string_find_byte_backward (&str, 1, 'e', &i)) _dbus_assert_not_reached ("Did find 'e'"); _dbus_assert (i == -1); if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i)) _dbus_assert_not_reached ("Didn't find 'e'"); _dbus_assert (i == 1); _dbus_string_free (&str); /* Hex encoding */ _dbus_string_init_const (&str, "cafebabe, this is a bogus hex string"); if (!_dbus_string_init (&other)) _dbus_assert_not_reached ("could not init string"); if (!_dbus_string_hex_decode (&str, 0, &end, &other, 0)) _dbus_assert_not_reached ("deccoded bogus hex string with no error"); _dbus_assert (end == 8); _dbus_string_free (&other); test_roundtrips (test_hex_roundtrip); _dbus_string_free (&str); { int found, found_len; _dbus_string_init_const (&str, "012\r\n567\n90"); if (!_dbus_string_find_eol (&str, 0, &found, &found_len) || found != 3 || found_len != 2) _dbus_assert_not_reached ("Did not find '\\r\\n'"); if (found != 3 || found_len != 2) _dbus_assert_not_reached ("invalid return values"); if (!_dbus_string_find_eol (&str, 5, &found, &found_len)) _dbus_assert_not_reached ("Did not find '\\n'"); if (found != 8 || found_len != 1) _dbus_assert_not_reached ("invalid return values"); if (_dbus_string_find_eol (&str, 9, &found, &found_len)) _dbus_assert_not_reached ("Found not expected '\\n'"); else if (found != 11 || found_len != 0) _dbus_assert_not_reached ("invalid return values '\\n'"); found = -1; found_len = -1; _dbus_string_init_const (&str, ""); if (_dbus_string_find_eol (&str, 0, &found, &found_len)) _dbus_assert_not_reached ("found an eol in an empty string"); _dbus_assert (found == 0); _dbus_assert (found_len == 0); found = -1; found_len = -1; _dbus_string_init_const (&str, "foobar"); if (_dbus_string_find_eol (&str, 0, &found, &found_len)) _dbus_assert_not_reached ("found eol in string that lacks one"); _dbus_assert (found == 6); _dbus_assert (found_len == 0); found = -1; found_len = -1; _dbus_string_init_const (&str, "foobar\n"); if (!_dbus_string_find_eol (&str, 0, &found, &found_len)) _dbus_assert_not_reached ("did not find eol in string that has one at end"); _dbus_assert (found == 6); _dbus_assert (found_len == 1); } { DBusString line; #define FIRST_LINE "this is a line" #define SECOND_LINE "this is a second line" /* third line is empty */ #define THIRD_LINE "" #define FOURTH_LINE "this is a fourth line" if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_append (&str, FIRST_LINE "\n" SECOND_LINE "\r\n" THIRD_LINE "\n" FOURTH_LINE)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_init (&line)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_pop_line (&str, &line)) _dbus_assert_not_reached ("failed to pop first line"); _dbus_assert (_dbus_string_equal_c_str (&line, FIRST_LINE)); if (!_dbus_string_pop_line (&str, &line)) _dbus_assert_not_reached ("failed to pop second line"); _dbus_assert (_dbus_string_equal_c_str (&line, SECOND_LINE)); if (!_dbus_string_pop_line (&str, &line)) _dbus_assert_not_reached ("failed to pop third line"); _dbus_assert (_dbus_string_equal_c_str (&line, THIRD_LINE)); if (!_dbus_string_pop_line (&str, &line)) _dbus_assert_not_reached ("failed to pop fourth line"); _dbus_assert (_dbus_string_equal_c_str (&line, FOURTH_LINE)); _dbus_string_free (&str); _dbus_string_free (&line); } { if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("no memory"); for (i = 0; i < 10000; i++) if (!_dbus_string_append (&str, "abcdefghijklmnopqrstuvwxyz")) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_set_length (&str, 10)) _dbus_assert_not_reached ("failed to set length"); /* actually compact */ if (!_dbus_string_compact (&str, 2048)) _dbus_assert_not_reached ("failed to compact after set_length"); /* peek inside to make sure it worked */ if (((DBusRealString *)&str)->allocated > 30) _dbus_assert_not_reached ("compacting string didn't do anything"); if (!_dbus_string_equal_c_str (&str, "abcdefghij")) _dbus_assert_not_reached ("unexpected content after compact"); /* compact nothing */ if (!_dbus_string_compact (&str, 2048)) _dbus_assert_not_reached ("failed to compact 2nd time"); if (!_dbus_string_equal_c_str (&str, "abcdefghij")) _dbus_assert_not_reached ("unexpected content after 2nd compact"); /* and make sure it still works...*/ if (!_dbus_string_append (&str, "123456")) _dbus_assert_not_reached ("failed to append after compact"); if (!_dbus_string_equal_c_str (&str, "abcdefghij123456")) _dbus_assert_not_reached ("unexpected content after append"); /* after growing automatically, this should do nothing */ if (!_dbus_string_compact (&str, 20000)) _dbus_assert_not_reached ("failed to compact after grow"); /* but this one will do something */ if (!_dbus_string_compact (&str, 0)) _dbus_assert_not_reached ("failed to compact after grow"); if (!_dbus_string_equal_c_str (&str, "abcdefghij123456")) _dbus_assert_not_reached ("unexpected content"); if (!_dbus_string_append (&str, "!@#$%")) _dbus_assert_not_reached ("failed to append after compact"); if (!_dbus_string_equal_c_str (&str, "abcdefghij123456!@#$%")) _dbus_assert_not_reached ("unexpected content"); _dbus_string_free (&str); } { const char two_strings[] = "one\ttwo"; if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_init (&other)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_append (&str, two_strings)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_split_on_byte (&str, '\t', &other)) _dbus_assert_not_reached ("no memory or delimiter not found"); if (strcmp (_dbus_string_get_data (&str), "one") != 0) _dbus_assert_not_reached ("left side after split on tab is wrong"); if (strcmp (_dbus_string_get_data (&other), "two") != 0) _dbus_assert_not_reached ("right side after split on tab is wrong"); _dbus_string_free (&str); _dbus_string_free (&other); } return TRUE; }