From 482dab2076282ef1195564fa60dd25c1ffb77682 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 31 Jan 2003 03:49:42 +0000 Subject: [PATCH] 2003-01-31 Havoc Pennington * doc/dbus-specification.sgml: fully specify the header. Add flags and major protocol version, and change header/body len to unsigned. * dbus/dbus-message-builder.c (append_saved_length): append length as uint32 * dbus/dbus-message.c (dbus_message_create_header): change header length and body length to unsigned. Add the new fields from the spec (_dbus_message_loader_return_buffer): unsigned header/body len --- ChangeLog | 14 ++++++ dbus/dbus-message-builder.c | 4 +- dbus/dbus-message.c | 92 ++++++++++++++++++++++++++++++-------- dbus/dbus-protocol.h | 3 ++ doc/dbus-specification.sgml | 105 +++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 197 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1407218..6ea0bfa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2003-01-31 Havoc Pennington + + * doc/dbus-specification.sgml: fully specify the header. Add + flags and major protocol version, and change header/body len to + unsigned. + + * dbus/dbus-message-builder.c (append_saved_length): append length + as uint32 + + * dbus/dbus-message.c (dbus_message_create_header): change header + length and body length to unsigned. Add the new fields from the + spec + (_dbus_message_loader_return_buffer): unsigned header/body len + 2003-01-30 Havoc Pennington * dbus/dbus-auth.c: rework to use only REJECTED, no diff --git a/dbus/dbus-message-builder.c b/dbus/dbus-message-builder.c index 8d01229..4731333 100644 --- a/dbus/dbus-message-builder.c +++ b/dbus/dbus-message-builder.c @@ -312,8 +312,8 @@ append_saved_length (DBusString *dest, return FALSE; } - if (!_dbus_marshal_int32 (dest, endian, - -1)) + if (!_dbus_marshal_uint32 (dest, endian, + -1)) { _dbus_warn ("failed to append a length\n"); return FALSE; diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index b485f63..3d0de77 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -422,6 +422,36 @@ set_int_field (DBusMessage *message, } static dbus_bool_t +set_uint_field (DBusMessage *message, + int field, + dbus_uint32_t value) +{ + int offset = message->header_fields[field].offset; + + _dbus_assert (!message->locked); + + if (offset < 0) + { + /* need to append the field */ + + switch (field) + { + default: + _dbus_assert_not_reached ("appending a uint field we don't support appending"); + return FALSE; + } + } + else + { + _dbus_marshal_set_uint32 (&message->header, + message->byte_order, + offset, value); + + return TRUE; + } +} + +static dbus_bool_t set_string_field (DBusMessage *message, int field, const char *value) @@ -581,19 +611,28 @@ static dbus_bool_t dbus_message_create_header (DBusMessage *message, const char *service, const char *name) -{ +{ + unsigned int flags; + if (!_dbus_string_append_byte (&message->header, message->byte_order)) return FALSE; - - if (!_dbus_string_append_len (&message->header, "\0\0\0", 3)) + + flags = 0; + if (!_dbus_string_append_byte (&message->header, flags)) + return FALSE; + + if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION)) + return FALSE; + + if (!_dbus_string_append_byte (&message->header, 0)) return FALSE; message->header_fields[FIELD_HEADER_LENGTH].offset = 4; - if (!_dbus_marshal_int32 (&message->header, message->byte_order, 0)) + if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0)) return FALSE; message->header_fields[FIELD_BODY_LENGTH].offset = 8; - if (!_dbus_marshal_int32 (&message->header, message->byte_order, 0)) + if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0)) return FALSE; message->header_fields[FIELD_CLIENT_SERIAL].offset = 12; @@ -635,13 +674,13 @@ _dbus_message_lock (DBusMessage *message) if (!message->locked) { /* Fill in our lengths */ - set_int_field (message, - FIELD_HEADER_LENGTH, - _dbus_string_get_length (&message->header)); + set_uint_field (message, + FIELD_HEADER_LENGTH, + _dbus_string_get_length (&message->header)); - set_int_field (message, - FIELD_BODY_LENGTH, - _dbus_string_get_length (&message->body)); + set_uint_field (message, + FIELD_BODY_LENGTH, + _dbus_string_get_length (&message->body)); message->locked = TRUE; } @@ -1955,6 +1994,7 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader, DBusMessage *message; const char *header_data; int byte_order, header_len, body_len; + dbus_uint32_t header_len_unsigned, body_len_unsigned; _dbus_string_get_const_data_len (&loader->data, &header_data, 0, 16); @@ -1971,18 +2011,34 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader, return; } - header_len = _dbus_unpack_int32 (byte_order, header_data + 4); - body_len = _dbus_unpack_int32 (byte_order, header_data + 8); + header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4); + body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8); - if (header_len < 16 || body_len < 0) + if (header_len_unsigned < 16) { - _dbus_verbose ("Message had broken too-small header or body len %d %d\n", - header_len, body_len); + _dbus_verbose ("Message had broken too-small header length %u\n", + header_len_unsigned); loader->corrupted = TRUE; return; } - if (_DBUS_ALIGN_VALUE (header_len, 8) != (unsigned int) header_len) + if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE || + body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE) + { + _dbus_verbose ("Header or body length too large (%u %u)\n", + header_len_unsigned, + body_len_unsigned); + loader->corrupted = TRUE; + return; + } + + /* Now that we know the values are in signed range, get + * rid of stupid unsigned, just causes bugs + */ + header_len = header_len_unsigned; + body_len = body_len_unsigned; + + if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned) { _dbus_verbose ("header length %d is not aligned to 8 bytes\n", header_len); @@ -1998,7 +2054,7 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader, return; } - if (_dbus_string_get_length (&loader->data) >= header_len + body_len) + if (_dbus_string_get_length (&loader->data) >= (header_len + body_len)) { HeaderField fields[FIELD_LAST]; int i; diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h index 774ccf2..0df6c2e 100644 --- a/dbus/dbus-protocol.h +++ b/dbus/dbus-protocol.h @@ -36,6 +36,9 @@ extern "C" { #define DBUS_LITTLE_ENDIAN ('l') /* LSB first */ #define DBUS_BIG_ENDIAN ('B') /* MSB first */ +/* Protocol version */ +#define DBUS_MAJOR_PROTOCOL_VERSION 0 + /* Data types */ #define DBUS_TYPE_INVALID 0 #define DBUS_TYPE_NIL 1 diff --git a/doc/dbus-specification.sgml b/doc/dbus-specification.sgml index 632575b..b8d80bb 100644 --- a/doc/dbus-specification.sgml +++ b/doc/dbus-specification.sgml @@ -83,7 +83,95 @@ Header Encoding - [document the required header fields and how they are encoded] + Following the mandatory fields, there are zero or more named fields (see + ), and then nul bytes + padding the header such that its total length in bytes is a multiple of + 8. + + + The header MUST begin with the following mandatory fields in the following + order: + + + + + Size + Description + + + + + 1 byte + Endianness flag; ASCII 'l' for little-endian + or ASCII 'B' for big-endian. + + + 1 byte + Bitwise OR of flags. Unknown flags + MUST be ignored. Currently-defined flags are described below. + + + + 1 byte + Major protocol version of the sending application. If + the major protocol version of the receiving application does not + match, the applications will not be able to communicate and the + D-BUS connection MUST be disconnected. The major protocol + version for this version of the specification is 0. + + + + 1 byte + A nul byte, reserved for future use. + Any value for this byte MUST be accepted. + + + + 4 bytes + An unsigned 32-bit integer in the + message's byte order, indicating the total length in bytes of + the header including named fields and any alignment padding. + MUST be a multiple of 8. + + + + 4 bytes + An unsigned 32-bit integer in the + message's byte order, indicating the total length in bytes of + the message body. + + + + 4 bytes + The message's serial number, a signed 32-bit integer in + the message's byte order. Applications MUST NOT reuse the same + serial number for different messages more often than 32-bit + integer wraparound. Serial numbers must be greater than + zero. + + + + + + + + Flags that can appear in the second byte of the header: + + + + + Hex value + Description + + + + + 0x1 + This message is an error reply. + + + + @@ -100,7 +188,22 @@ invent their own header fields; only changes to this specification may introduce new header fields. + + + Header Alignment Padding + + To allow implementations to keep the header and the body in a single + buffer while keeping data types aligned, the total length of the header + must be a multiple of 8 bytes. To achieve this, the header MUST be padded + with nul bytes to align its total length on an 8-byte boundary. + The minimum number of padding bytes MUST be used. Because all possible + named fields use at least 8 bytes, implementations can distinguish + padding (which must be less than 8 bytes) from additional named fields + (which must be at least 8 bytes). + + + Message Arguments -- 2.7.4