25#include "dbus/dbus-shared.h"
26#include "dbus-marshal-header.h"
27#include "dbus-marshal-recursive.h"
28#include "dbus-marshal-byteswap.h"
47#define FIELDS_ARRAY_SIGNATURE_OFFSET 6
49#define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET 7
53#define BYTE_ORDER_OFFSET 0
59#define VERSION_OFFSET 3
61#define BODY_LENGTH_OFFSET 4
63#define SERIAL_OFFSET 8
65#define FIELDS_ARRAY_LENGTH_OFFSET 12
67#define FIRST_FIELD_OFFSET 16
91#define EXPECTED_TYPE_OF_FIELD(field) (_dbus_header_field_types[field].type)
94#define MAX_POSSIBLE_HEADER_PADDING 7
115 unpadded_len = _dbus_string_get_length (&header->
data);
120 header->
padding = _dbus_string_get_length (&header->
data) - unpadded_len;
126#define HEADER_END_BEFORE_PADDING(header) \
127 (_dbus_string_get_length (&(header)->data) - (header)->padding)
137_dbus_header_cache_invalidate_all (
DBusHeader *header)
165 _dbus_verbose (
"cached value_pos %d for field %d\n",
190_dbus_header_cache_revalidate (
DBusHeader *header)
205 &_dbus_header_signature_str,
216 unsigned char field_code;
232 _dbus_header_cache_one (header, field_code, &variant);
252 if (header->
fields[field].
value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
253 _dbus_header_cache_revalidate (header);
255 if (header->
fields[field].
value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT)
270_dbus_header_cache_known_nonexistent (
DBusHeader *header,
275 return (header->
fields[field].
value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT);
297 unsigned char field_byte;
302 padding = _dbus_string_get_length (writer->
value_str) - start;
318 &contained_type, 0, &variant))
335 _dbus_string_get_length (writer->
value_str) - start - padding);
362#ifndef DBUS_DISABLE_ASSERT
364 unsigned char v_BYTE;
408 dbus_uint32_t serial)
452 _dbus_header_cache_invalidate_all (header);
499 _dbus_string_get_length (&header->
data)))
534 const char *destination,
536 const char *interface,
538 const char *error_name)
540 unsigned char v_BYTE;
541 dbus_uint32_t v_UINT32;
549 !(interface || member || error_name));
552 if (!reserve_header_padding (header))
556 &_dbus_header_signature_str, 0,
565 v_BYTE = message_type;
591 &_dbus_header_signature_str,
600 if (!write_basic_field (&array,
607 if (destination !=
NULL)
609 if (!write_basic_field (&array,
619 if (interface !=
NULL)
621 if (!write_basic_field (&array,
630 if (!write_basic_field (&array,
637 if (error_name !=
NULL)
639 if (!write_basic_field (&array,
649 correct_header_padding (header);
655 _dbus_string_get_length (&header->
data) - header->
padding);
656 correct_header_padding (header);
682 int *fields_array_len,
690 dbus_uint32_t header_len_unsigned;
691 dbus_uint32_t fields_array_len_unsigned;
692 dbus_uint32_t body_len_unsigned;
698 _dbus_assert (start == (
int) _DBUS_ALIGN_VALUE (start, 8));
704 *validity = DBUS_INVALID_BAD_BYTE_ORDER;
712 if (fields_array_len_unsigned > (
unsigned) max_message_length)
714 *validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH;
722 if (body_len_unsigned > (
unsigned) max_message_length)
724 *validity = DBUS_INVALID_INSANE_BODY_LENGTH;
729 header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8);
735 if (body_len_unsigned + header_len_unsigned > (
unsigned) max_message_length)
737 *validity = DBUS_INVALID_MESSAGE_TOO_LONG;
745 *body_len = body_len_unsigned;
746 *fields_array_len = fields_array_len_unsigned;
747 *header_len = header_len_unsigned;
751 _dbus_verbose (
"have %d bytes, need body %u + header %u = %u\n",
752 len, body_len_unsigned, header_len_unsigned,
753 body_len_unsigned + header_len_unsigned);
755 return (body_len_unsigned + header_len_unsigned) <= (unsigned) len;
761#define REQUIRE_FIELD(name) do { if (header->fields[DBUS_HEADER_FIELD_##name].value_pos < 0) return DBUS_INVALID_MISSING_##name; } while (0)
766 REQUIRE_FIELD (INTERFACE);
769 REQUIRE_FIELD (PATH);
770 REQUIRE_FIELD (MEMBER);
773 REQUIRE_FIELD (ERROR_NAME);
774 REQUIRE_FIELD (REPLY_SERIAL);
777 REQUIRE_FIELD (REPLY_SERIAL);
797 dbus_uint32_t v_UINT32;
809 _dbus_assert (_dbus_header_field_types[field].code == field);
812 if (type != expected_type)
814 _dbus_verbose (
"Field %d should have type %d but has %d\n",
815 field, expected_type, type);
816 return DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE;
822 _dbus_verbose (
"Header field %d seen a second time\n", field);
823 return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE;
827 _dbus_verbose (
"initially caching field %d\n", field);
828 _dbus_header_cache_one (header, field, variant_reader);
830 string_validation_func =
NULL;
849 &value_str, &value_pos);
850 str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4;
861 bad_string_code = DBUS_INVALID_BAD_DESTINATION;
865 bad_string_code = DBUS_INVALID_BAD_INTERFACE;
869 _dbus_string_get_length (&_dbus_local_interface_str),
870 value_str, str_data_pos))
872 _dbus_verbose (
"Message is on the local interface\n");
873 return DBUS_INVALID_USES_LOCAL_INTERFACE;
879 bad_string_code = DBUS_INVALID_BAD_MEMBER;
884 bad_string_code = DBUS_INVALID_BAD_ERROR_NAME;
889 bad_string_code = DBUS_INVALID_BAD_SENDER;
894 string_validation_func =
NULL;
898 _dbus_string_get_length (&_dbus_local_path_str),
899 value_str, str_data_pos))
901 _dbus_verbose (
"Message is from the local path\n");
902 return DBUS_INVALID_USES_LOCAL_PATH;
910 return DBUS_INVALID_BAD_SERIAL;
920 string_validation_func =
NULL;
925 string_validation_func =
NULL;
933 if (string_validation_func)
944 _dbus_verbose (
"Validating string header field; code %d if fails\n",
947 if (!(*string_validation_func) (value_str, str_data_pos, len))
948 return bad_string_code;
983 int fields_array_len,
992 unsigned char v_byte;
993 dbus_uint32_t v_uint32;
994 dbus_uint32_t serial;
1000 len = _dbus_string_get_length (str);
1007 _dbus_verbose (
"Failed to copy buffer into new header\n");
1012 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1014 leftover = len - header_len - body_len;
1034 _dbus_assert (header_len == (
int) _DBUS_ALIGN_VALUE (padding_start, 8));
1035 _dbus_assert (header_len == padding_start + padding_len);
1037 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1041 *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
1046 header->
padding = padding_len;
1048 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1060 &_dbus_header_signature_str, 0,
1082 *validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
1102 *validity = DBUS_INVALID_BAD_PROTOCOL_VERSION;
1122 *validity = DBUS_INVALID_BAD_SERIAL;
1134 unsigned char field_code;
1146 _dbus_verbose (
"invalid header field code\n");
1147 *validity = DBUS_INVALID_HEADER_FIELD_CODE;
1153 _dbus_verbose (
"unknown header field code %d, skipping\n",
1161 v = load_and_validate_field (header, field_code, &variant_reader);
1164 _dbus_verbose (
"Field %d was invalid\n", field_code);
1182 v = check_mandatory_fields (header);
1185 _dbus_verbose (
"Mandatory fields were missing, code %d\n", v);
1228find_field_for_modification (
DBusHeader *header,
1239 &_dbus_header_signature_str,
1249 unsigned char field_code;
1256 if (field_code == (
unsigned) field)
1289 if (!reserve_header_padding (header))
1293 if (_dbus_header_cache_check (header, field))
1298 if (!find_field_for_modification (header, field,
1299 &reader, &realign_root))
1302 if (!set_basic_field (&reader, field, type, value, &realign_root))
1312 &_dbus_header_signature_str,
1321 &_dbus_header_signature_str,
1330 if (!write_basic_field (&array,
1331 field, type, value))
1338 correct_header_padding (header);
1344 _dbus_header_cache_invalidate_all (header);
1367 _dbus_assert (_dbus_header_field_types[field].code == field);
1374 if (!_dbus_header_cache_check (header, field))
1406 if (!_dbus_header_cache_check (header, field))
1410 *str = &header->
data;
1431 if (_dbus_header_cache_known_nonexistent (header, field))
1437 if (!find_field_for_modification (header, field,
1438 &reader, &realign_root))
1441 if (!reserve_header_padding (header))
1448 correct_header_padding (header);
1450 _dbus_header_cache_invalidate_all (header);
1452 _dbus_assert (!_dbus_header_cache_check (header, field));
1470 unsigned char *flags_p;
1491 const unsigned char *flags_p;
1493 flags_p = _dbus_string_get_const_udata_len (&header->
data,
FLAGS_OFFSET, 1);
1495 return (*flags_p & flag) != 0;
1512 if (byte_order == new_order)
1537 &_dbus_header_signature_str,
1547 unsigned char field_code;
1556 if (!reserve_header_padding (header))
1562 correct_header_padding (header);
1563 _dbus_header_cache_invalidate_all (header);
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define _DBUS_INT32_MAX
Maximum value of type "int32".
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
dbus_bool_t _dbus_type_writer_write_basic(DBusTypeWriter *writer, int type, const void *value)
Writes out a basic type.
void _dbus_type_reader_recurse(DBusTypeReader *reader, DBusTypeReader *sub)
Initialize a new reader pointing to the first type and corresponding value that's a child of the curr...
DBusValidity
This is primarily used in unit testing, so we can verify that each invalid message is invalid for the...
void _dbus_header_update_lengths(DBusHeader *header, int body_len)
Fills in the correct body length.
dbus_bool_t _dbus_header_copy(const DBusHeader *header, DBusHeader *dest)
Initializes dest with a copy of the given header.
#define BODY_LENGTH_OFFSET
Offset to body length from start of header.
void _dbus_type_writer_init_values_only(DBusTypeWriter *writer, int byte_order, const DBusString *type_str, int type_pos, DBusString *value_str, int value_pos)
Like _dbus_type_writer_init(), except the type string passed in should correspond to an existing sign...
int _dbus_type_reader_get_value_pos(const DBusTypeReader *reader)
Gets the current position in the value block.
void _dbus_type_reader_init(DBusTypeReader *reader, int byte_order, const DBusString *type_str, int type_pos, const DBusString *value_str, int value_pos)
Initializes a type reader.
#define EXPECTED_TYPE_OF_FIELD(field)
Macro to look up the correct type for a field.
dbus_bool_t _dbus_validate_error_name(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid error name in the D-Bus protocol.
dbus_bool_t _dbus_header_set_field_basic(DBusHeader *header, int field, int type, const void *value)
Sets the value of a field with basic type.
int _dbus_header_get_message_type(DBusHeader *header)
Gets the type of the message.
dbus_bool_t _dbus_header_get_field_basic(DBusHeader *header, int field, int type, void *value)
Gets the value of a field with basic type.
#define SERIAL_OFFSET
Offset to client serial from start of header.
void _dbus_marshal_set_uint32(DBusString *str, int pos, dbus_uint32_t value, int byte_order)
Sets the 4 bytes at the given offset to a marshaled unsigned integer, replacing anything found there ...
dbus_bool_t _dbus_type_writer_recurse(DBusTypeWriter *writer, int container_type, const DBusString *contained_type, int contained_type_start, DBusTypeWriter *sub)
Opens a new container and writes out the initial information for that container.
#define VERSION_OFFSET
Offset to version from start of header.
dbus_bool_t _dbus_header_get_flag(DBusHeader *header, dbus_uint32_t flag)
Gets a message flag bit, returning TRUE if the bit is set.
void _dbus_marshal_byteswap(const DBusString *signature, int signature_start, int old_byte_order, int new_byte_order, DBusString *value_str, int value_pos)
Byteswaps the marshaled data in the given value_str.
char _dbus_header_get_byte_order(const DBusHeader *header)
Returns the header's byte order.
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)
Given data long enough to contain the length of the message body and the fields array,...
void _dbus_header_reinit(DBusHeader *header)
Re-initializes a header that was previously initialized and never freed.
dbus_uint32_t _dbus_marshal_read_uint32(const DBusString *str, int pos, int byte_order, int *new_pos)
Convenience function to demarshal a 32 bit unsigned integer.
dbus_bool_t _dbus_validate_member(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid member name in the D-Bus protocol.
dbus_bool_t _dbus_type_reader_next(DBusTypeReader *reader)
Skip to the next value on this "level".
dbus_bool_t _dbus_header_delete_field(DBusHeader *header, int field)
Deletes a field, if it exists.
dbus_bool_t _dbus_header_remove_unknown_fields(DBusHeader *header)
Remove every header field not known to this version of dbus.
dbus_uint32_t _dbus_header_get_serial(DBusHeader *header)
See dbus_message_get_serial()
#define FLAGS_OFFSET
Offset to flags from start of header.
#define FIELDS_ARRAY_SIGNATURE_OFFSET
Offset from start of _dbus_header_signature_str to the signature of the fields array.
#define MAX_POSSIBLE_HEADER_PADDING
The most padding we could ever need for a header.
dbus_bool_t _dbus_type_reader_delete(DBusTypeReader *reader, const DBusTypeReader *realign_root)
Recursively deletes any value pointed to by the reader, leaving the reader valid to continue reading.
void _dbus_type_reader_read_basic(const DBusTypeReader *reader, void *value)
Reads a basic-typed value, as with _dbus_marshal_read_basic().
#define BYTE_ORDER_OFFSET
Offset to byte order from start of header.
#define FIRST_FIELD_OFFSET
Offset to first field in header.
dbus_bool_t _dbus_validate_interface(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid interface name in the D-Bus protocol.
dbus_bool_t _dbus_type_reader_set_basic(DBusTypeReader *reader, const void *value, const DBusTypeReader *realign_root)
Sets a new value for the basic type value pointed to by the reader, leaving the reader valid to conti...
DBusValidity _dbus_validate_body_with_reason(const DBusString *expected_signature, int expected_signature_start, int byte_order, int *bytes_remaining, const DBusString *value_str, int value_pos, int len)
Verifies that the range of value_str from value_pos to value_end is a legitimate value of type expect...
void _dbus_marshal_read_basic(const DBusString *str, int pos, int type, void *value, int byte_order, int *new_pos)
Demarshals a basic-typed value.
_DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE)
Static DBusString containing the signature of a message header.
int _dbus_type_reader_get_current_type(const DBusTypeReader *reader)
Gets the type of the value the reader is currently pointing to; or for a types-only reader gets the t...
void _dbus_header_free(DBusHeader *header)
Frees a header.
dbus_bool_t _dbus_validate_bus_name(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid bus name in the D-Bus protocol.
dbus_bool_t _dbus_header_init(DBusHeader *header)
Initializes a header, but doesn't prepare it for use; to make the header valid, you have to call _dbu...
dbus_bool_t _dbus_header_create(DBusHeader *header, int byte_order, int message_type, const char *destination, const char *path, const char *interface, const char *member, const char *error_name)
Fills in the primary fields of the header, so the header is ready for use.
#define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET
Offset from start of _dbus_header_signature_str to the signature of an element of the fields array.
dbus_bool_t _dbus_type_writer_unrecurse(DBusTypeWriter *writer, DBusTypeWriter *sub)
Closes a container created by _dbus_type_writer_recurse() and writes any additional information to th...
dbus_bool_t _dbus_type_writer_append_array(DBusTypeWriter *writer, const DBusString *contained_type, int contained_type_start, DBusTypeWriter *sub)
Append to an existing array.
void _dbus_header_toggle_flag(DBusHeader *header, dbus_uint32_t flag, dbus_bool_t value)
Toggles a message flag bit, turning on the bit if value = TRUE and flipping it off if value = FALSE.
void _dbus_header_set_serial(DBusHeader *header, dbus_uint32_t serial)
Sets the serial number of a header.
dbus_bool_t _dbus_header_load(DBusHeader *header, DBusValidationMode mode, DBusValidity *validity, int byte_order, int fields_array_len, int header_len, int body_len, const DBusString *str)
Creates a message header from potentially-untrusted data.
void _dbus_header_byteswap(DBusHeader *header, int new_order)
Swaps the header into the given order if required.
#define FIELDS_ARRAY_LENGTH_OFFSET
Offset to fields array length from start of header.
#define HEADER_END_BEFORE_PADDING(header)
Compute the end of the header, ignoring padding.
dbus_bool_t _dbus_header_get_field_raw(DBusHeader *header, int field, const DBusString **str, int *pos)
Gets the raw marshaled data for a field.
#define TYPE_OFFSET
Offset to type from start of header.
DBusValidationMode
This is used rather than a bool for high visibility.
@ DBUS_VALIDITY_UNKNOWN_OOM_ERROR
can't determine validity due to OOM
@ DBUS_VALID
the data is valid
#define DBUS_HEADER_FIELD_UNIX_FDS
Header field code for the number of unix file descriptors associated with this message.
#define DBUS_HEADER_FIELD_INVALID
Not equal to any valid header field code.
#define DBUS_MESSAGE_TYPE_METHOD_CALL
Message type of a method call message, see dbus_message_get_type()
#define DBUS_HEADER_FIELD_PATH
Header field code for the path - the path is the object emitting a signal or the object receiving a m...
#define DBUS_HEADER_FIELD_REPLY_SERIAL
Header field code for a reply serial, used to match a DBUS_MESSAGE_TYPE_METHOD_RETURN message with th...
#define DBUS_HEADER_FIELD_CONTAINER_INSTANCE
Header field code for the container instance that sent this message.
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
#define DBUS_HEADER_FIELD_INTERFACE
Header field code for the interface containing a member (method or signal).
#define DBUS_HEADER_FIELD_MEMBER
Header field code for a member (method or signal).
#define DBUS_MESSAGE_TYPE_ERROR
Message type of an error reply message, see dbus_message_get_type()
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
#define DBUS_TYPE_BYTE
Type code marking an 8-bit unsigned integer.
#define DBUS_HEADER_FIELD_SENDER
Header field code for the sender of a message; usually initialized by the message bus.
#define DBUS_HEADER_FIELD_SIGNATURE
Header field code for the type signature of a message.
#define DBUS_MESSAGE_TYPE_METHOD_RETURN
Message type of a method return message, see dbus_message_get_type()
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
#define DBUS_MESSAGE_TYPE_SIGNAL
Message type of a signal message, see dbus_message_get_type()
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
#define DBUS_HEADER_SIGNATURE
Header format is defined as a signature: byte byte order byte message type ID byte flags byte protoco...
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
#define DBUS_HEADER_FIELD_LAST
Value of the highest-numbered header field code, can be used to determine the size of an array indexe...
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
#define DBUS_LITTLE_ENDIAN
Code marking LSB-first byte order in the wire protocol.
#define DBUS_HEADER_FIELD_ERROR_NAME
Header field code for an error name (found in DBUS_MESSAGE_TYPE_ERROR messages).
#define DBUS_MESSAGE_TYPE_INVALID
This value is never a valid message type, see dbus_message_get_type()
#define DBUS_HEADER_FIELD_DESTINATION
Header field code for the destination bus name of a message.
#define DBUS_MAJOR_PROTOCOL_VERSION
Protocol version.
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string,...
#define DBUS_BIG_ENDIAN
Code marking MSB-first byte order in the wire protocol.
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
#define DBUS_PATH_LOCAL
The object path used in local/in-process-generated messages.
#define DBUS_INTERFACE_LOCAL
This is a special interface whose methods can only be invoked by the local implementation (messages f...
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
dbus_bool_t _dbus_string_validate_nul(const DBusString *str, int start, int len)
Checks that the given range of the string is all nul bytes.
dbus_bool_t _dbus_string_equal_substring(const DBusString *a, int a_start, int a_len, const DBusString *b, int b_start)
Tests two sub-parts of two DBusString for equality.
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
dbus_bool_t _dbus_string_init_preallocated(DBusString *str, int allocate_size)
Initializes a string that can be up to the given allocation size before it has to realloc.
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
void _dbus_string_delete(DBusString *str, int start, int len)
Deletes a segment of a DBusString with length len starting at start.
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
dbus_bool_t _dbus_string_align_length(DBusString *str, int alignment)
Align the length of a string to a specific alignment (typically 4 or 8) by appending nul bytes to the...
dbus_bool_t _dbus_string_copy_len(const DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_copy(), but can copy a segment from the middle of the source string.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
The type reader is an iterator for reading values from a block of values.
The type writer is an iterator for writing to a block of values.
int start_pos
position of first element in the array
int value_pos
next position to write
union DBusTypeWriter::@3 u
class-specific data
int len_pos
position of length of the array
DBusString * value_str
where to write values