From fddbc09c4a9125fcb168fb31ff300d4132919ea6 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 27 Jan 2005 23:39:26 +0000 Subject: 2005-01-27 Havoc Pennington * dbus/dbus-message.c: byteswap the message if you init an iterator to read/write from it * dbus/dbus-marshal-byteswap.c: new file implementing _dbus_marshal_byteswap() * dbus/dbus-marshal-basic.c: add _dbus_swap_array() --- ChangeLog | 10 ++ dbus/Makefile.am | 3 + dbus/dbus-marshal-basic.c | 77 +++++++----- dbus/dbus-marshal-basic.h | 4 + dbus/dbus-marshal-byteswap-util.c | 105 +++++++++++++++++ dbus/dbus-marshal-byteswap.c | 232 +++++++++++++++++++++++++++++++++++++ dbus/dbus-marshal-byteswap.h | 42 +++++++ dbus/dbus-marshal-header.c | 22 ++++ dbus/dbus-marshal-header.h | 3 +- dbus/dbus-marshal-recursive-util.c | 99 +++++++++++++++- dbus/dbus-marshal-recursive.h | 4 +- dbus/dbus-marshal-validate.c | 7 ++ dbus/dbus-marshal-validate.h | 1 - dbus/dbus-message.c | 80 ++++++++++--- dbus/dbus-test.c | 6 + dbus/dbus-test.h | 1 + 16 files changed, 645 insertions(+), 51 deletions(-) create mode 100644 dbus/dbus-marshal-byteswap-util.c create mode 100644 dbus/dbus-marshal-byteswap.c create mode 100644 dbus/dbus-marshal-byteswap.h diff --git a/ChangeLog b/ChangeLog index 3a11130c..c1d24655 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2005-01-27 Havoc Pennington + + * dbus/dbus-message.c: byteswap the message if you init an + iterator to read/write from it + + * dbus/dbus-marshal-byteswap.c: new file implementing + _dbus_marshal_byteswap() + + * dbus/dbus-marshal-basic.c: add _dbus_swap_array() + 2005-01-26 Havoc Pennington * dbus/dbus-marshal-validate-util.c: break this out (and fix diff --git a/dbus/Makefile.am b/dbus/Makefile.am index 36a6ec8d..2d08be6c 100644 --- a/dbus/Makefile.am +++ b/dbus/Makefile.am @@ -56,6 +56,8 @@ DBUS_LIB_SOURCES= \ dbus-keyring.h \ dbus-marshal-header.c \ dbus-marshal-header.h \ + dbus-marshal-byteswap.c \ + dbus-marshal-byteswap.h \ dbus-marshal-recursive.c \ dbus-marshal-recursive.h \ dbus-marshal-validate.c \ @@ -125,6 +127,7 @@ DBUS_UTIL_SOURCES= \ dbus-auth-util.c \ dbus-mainloop.c \ dbus-mainloop.h \ + dbus-marshal-byteswap-util.c \ dbus-marshal-recursive-util.c \ dbus-marshal-validate-util.c \ dbus-message-factory.c \ diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c index 5cb43b88..cd5d4e45 100644 --- a/dbus/dbus-marshal-basic.c +++ b/dbus/dbus-marshal-basic.c @@ -820,6 +820,53 @@ marshal_1_octets_array (DBusString *str, return TRUE; } +/** + * Swaps the elements of an array to the opposite byte order + * + * @param data start of array + * @param n_elements number of elements + * @param alignment size of each element + */ +void +_dbus_swap_array (unsigned char *data, + int n_elements, + int alignment) +{ + unsigned char *d; + unsigned char *end; + + _dbus_assert (_DBUS_ALIGN_ADDRESS (data, alignment) == data); + + /* we use const_data and cast it off so DBusString can be a const string + * for the unit tests. don't ask. + */ + d = data; + end = d + (n_elements * alignment); + + if (alignment == 8) + { + while (d != end) + { +#ifdef DBUS_HAVE_INT64 + *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d)); +#else + swap_8_bytes ((DBusBasicValue*) d); +#endif + d += 8; + } + } + else + { + _dbus_assert (alignment == 4); + + while (d != end) + { + *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d)); + d += 4; + } + } +} + static void swap_array (DBusString *str, int array_start, @@ -831,37 +878,11 @@ swap_array (DBusString *str, if (byte_order != DBUS_COMPILER_BYTE_ORDER) { - unsigned char *d; - unsigned char *end; - /* we use const_data and cast it off so DBusString can be a const string * for the unit tests. don't ask. */ - d = (unsigned char*) _dbus_string_get_const_data (str) + array_start; - end = d + n_elements * alignment; - - if (alignment == 8) - { - while (d != end) - { -#ifdef DBUS_HAVE_INT64 - *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d)); -#else - swap_8_bytes ((DBusBasicValue*) d); -#endif - d += 8; - } - } - else - { - _dbus_assert (alignment == 4); - - while (d != end) - { - *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d)); - d += 4; - } - } + _dbus_swap_array ((unsigned char*) (_dbus_string_get_const_data (str) + array_start), + n_elements, alignment); } } diff --git a/dbus/dbus-marshal-basic.h b/dbus/dbus-marshal-basic.h index d8ded1ca..375f2a3e 100644 --- a/dbus/dbus-marshal-basic.h +++ b/dbus/dbus-marshal-basic.h @@ -218,4 +218,8 @@ const char* _dbus_type_to_string (int typecode); int _dbus_first_type_in_signature (const DBusString *str, int pos); +void _dbus_swap_array (unsigned char *data, + int n_elements, + int alignment); + #endif /* DBUS_MARSHAL_BASIC_H */ diff --git a/dbus/dbus-marshal-byteswap-util.c b/dbus/dbus-marshal-byteswap-util.c new file mode 100644 index 00000000..eeea539c --- /dev/null +++ b/dbus/dbus-marshal-byteswap-util.c @@ -0,0 +1,105 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-marshal-byteswap-util.c Would be in dbus-marshal-byteswap.c but tests/bus only + * + * Copyright (C) 2005 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include + +#ifdef DBUS_BUILD_TESTS +#include "dbus-marshal-byteswap.h" +#include "dbus-test.h" +#include + +static void +do_byteswap_test (int byte_order) +{ + int sequence; + DBusString signature; + DBusString body; + int opposite_order; + + if (!_dbus_string_init (&signature) || !_dbus_string_init (&body)) + _dbus_assert_not_reached ("oom"); + + opposite_order = byte_order == DBUS_LITTLE_ENDIAN ? DBUS_BIG_ENDIAN : DBUS_LITTLE_ENDIAN; + + sequence = 0; + while (dbus_internal_do_not_use_generate_bodies (sequence, + byte_order, + &signature, &body)) + { + DBusString copy; + DBusTypeReader body_reader; + DBusTypeReader copy_reader; + + if (!_dbus_string_init (©)) + _dbus_assert_not_reached ("oom"); + + if (!_dbus_string_copy (&body, 0, ©, 0)) + _dbus_assert_not_reached ("oom"); + + _dbus_marshal_byteswap (&signature, 0, + byte_order, + opposite_order, + ©, 0); + + _dbus_type_reader_init (&body_reader, byte_order, &signature, 0, + &body, 0); + _dbus_type_reader_init (©_reader, opposite_order, &signature, 0, + ©, 0); + + if (!_dbus_type_reader_equal_values (&body_reader, ©_reader)) + { + _dbus_verbose_bytes_of_string (&signature, 0, + _dbus_string_get_length (&signature)); + _dbus_verbose_bytes_of_string (&body, 0, + _dbus_string_get_length (&body)); + _dbus_verbose_bytes_of_string (©, 0, + _dbus_string_get_length (©)); + + _dbus_warn ("Byte-swapped data did not have same values as original data\n"); + _dbus_assert_not_reached ("test failed"); + } + + _dbus_string_free (©); + + _dbus_string_set_length (&signature, 0); + _dbus_string_set_length (&body, 0); + ++sequence; + } + + _dbus_string_free (&signature); + _dbus_string_free (&body); + + printf (" %d blocks swapped from order '%c' to '%c'\n", + sequence, byte_order, opposite_order); +} + +dbus_bool_t +_dbus_marshal_byteswap_test (void) +{ + do_byteswap_test (DBUS_LITTLE_ENDIAN); + do_byteswap_test (DBUS_BIG_ENDIAN); + + return TRUE; +} + +#endif /* DBUS_BUILD_TESTS */ diff --git a/dbus/dbus-marshal-byteswap.c b/dbus/dbus-marshal-byteswap.c new file mode 100644 index 00000000..434d7e4b --- /dev/null +++ b/dbus/dbus-marshal-byteswap.c @@ -0,0 +1,232 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-marshal-byteswap.c Swap a block of marshaled data + * + * Copyright (C) 2005 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "dbus-marshal-byteswap.h" +#include "dbus-marshal-basic.h" + +/** + * @addtogroup DBusMarshal + * @{ + */ + +static void +byteswap_body_helper (DBusTypeReader *reader, + dbus_bool_t walk_reader_to_end, + int old_byte_order, + int new_byte_order, + unsigned char *p, + unsigned char **new_p) +{ + int current_type; + + while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) + { + switch (current_type) + { + case DBUS_TYPE_BYTE: + ++p; + break; + + case DBUS_TYPE_BOOLEAN: + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + { + p = _DBUS_ALIGN_ADDRESS (p, 4); + *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p)); + p += 4; + } + break; + + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + case DBUS_TYPE_DOUBLE: + { + p = _DBUS_ALIGN_ADDRESS (p, 8); +#ifdef DBUS_HAVE_INT64 + *((dbus_uint64_t*)p) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)p)); +#else + _dbus_swap_array (p, 1, 8); +#endif + p += 8; + } + break; + + case DBUS_TYPE_ARRAY: + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + { + dbus_uint32_t array_len; + + p = _DBUS_ALIGN_ADDRESS (p, 4); + + array_len = _dbus_unpack_uint32 (old_byte_order, p); + + *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p)); + p += 4; + + if (current_type == DBUS_TYPE_ARRAY) + { + int elem_type; + int alignment; + + elem_type = _dbus_type_reader_get_element_type (reader); + alignment = _dbus_type_get_alignment (elem_type); + + p = _DBUS_ALIGN_ADDRESS (p, alignment); + + if (_dbus_type_is_fixed (elem_type)) + { + if (alignment > 1) + _dbus_swap_array (p, array_len / alignment, alignment); + } + else + { + DBusTypeReader sub; + const unsigned char *array_end; + + array_end = p + array_len; + + _dbus_type_reader_recurse (reader, &sub); + + while (p < array_end) + { + byteswap_body_helper (&sub, + FALSE, + old_byte_order, + new_byte_order, + p, &p); + } + } + } + else + { + _dbus_assert (current_type == DBUS_TYPE_STRING || + current_type == DBUS_TYPE_OBJECT_PATH); + + p += (array_len + 1); /* + 1 for nul */ + } + } + break; + + case DBUS_TYPE_SIGNATURE: + { + dbus_uint32_t sig_len; + + sig_len = *p; + + p += (sig_len + 2); /* +2 for len and nul */ + } + break; + + case DBUS_TYPE_VARIANT: + { + /* 1 byte sig len, sig typecodes, align to + * contained-type-boundary, values. + */ + dbus_uint32_t sig_len; + DBusString sig; + DBusTypeReader sub; + int contained_alignment; + + sig_len = *p; + ++p; + + _dbus_string_init_const_len (&sig, p, sig_len); + + p += (sig_len + 1); /* 1 for nul */ + + contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (&sig, 0)); + + p = _DBUS_ALIGN_ADDRESS (p, contained_alignment); + + _dbus_type_reader_init_types_only (&sub, &sig, 0); + + byteswap_body_helper (&sub, FALSE, old_byte_order, new_byte_order, p, &p); + } + break; + + case DBUS_TYPE_STRUCT: + { + DBusTypeReader sub; + + p = _DBUS_ALIGN_ADDRESS (p, 8); + + _dbus_type_reader_recurse (reader, &sub); + + byteswap_body_helper (&sub, TRUE, old_byte_order, new_byte_order, p, &p); + } + break; + + default: + _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); + break; + } + + if (walk_reader_to_end) + _dbus_type_reader_next (reader); + else + break; + } + + if (new_p) + *new_p = p; +} + +/** + * Byteswaps the marshaled data in the given value_str. + * + * @param signature the types in the value_str + * @param signature_start where in signature is the signature + * @param old_byte_order the old byte order + * @param new_byte_order the new byte order + * @param value_str the string containing the body + * @param value_pos where the values start + */ +void +_dbus_marshal_byteswap (const DBusString *signature, + int signature_start, + int old_byte_order, + int new_byte_order, + DBusString *value_str, + int value_pos) +{ + DBusTypeReader reader; + + _dbus_assert (value_pos >= 0); + _dbus_assert (value_pos <= _dbus_string_get_length (value_str)); + + if (old_byte_order == new_byte_order) + return; + + _dbus_type_reader_init_types_only (&reader, + signature, signature_start); + + byteswap_body_helper (&reader, TRUE, + old_byte_order, new_byte_order, + _dbus_string_get_data_len (value_str, value_pos, 0), + NULL); +} + +/** @} */ + +/* Tests in dbus-marshal-byteswap-util.c */ diff --git a/dbus/dbus-marshal-byteswap.h b/dbus/dbus-marshal-byteswap.h new file mode 100644 index 00000000..e33cd74f --- /dev/null +++ b/dbus/dbus-marshal-byteswap.h @@ -0,0 +1,42 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-marshal-byteswap.h Swap a block of marshaled data + * + * Copyright (C) 2005 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef DBUS_MARSHAL_BYTESWAP_H +#define DBUS_MARSHAL_BYTESWAP_H + +#include +#include +#include + +#ifndef PACKAGE +#error "config.h not included here" +#endif + +void _dbus_marshal_byteswap (const DBusString *signature, + int signature_start, + int old_byte_order, + int new_byte_order, + DBusString *value_str, + int value_pos); + +#endif /* DBUS_MARSHAL_BYTESWAP_H */ diff --git a/dbus/dbus-marshal-header.c b/dbus/dbus-marshal-header.c index 6102b6f0..b5a8d3d7 100644 --- a/dbus/dbus-marshal-header.c +++ b/dbus/dbus-marshal-header.c @@ -23,6 +23,7 @@ #include "dbus-marshal-header.h" #include "dbus-marshal-recursive.h" +#include "dbus-marshal-byteswap.h" /** * @addtogroup DBusMarshal @@ -1448,6 +1449,27 @@ _dbus_header_get_flag (DBusHeader *header, return (*flags_p & flag) != 0; } +/** + * Swaps the header into the given order if required. + * + * @param header the header + * @param new_order the new byte order + */ +void +_dbus_header_byteswap (DBusHeader *header, + int new_order) +{ + if (header->byte_order == new_order) + return; + + _dbus_marshal_byteswap (&_dbus_header_signature_str, + 0, header->byte_order, + new_order, + &header->data, 0); + + header->byte_order = new_order; +} + /** @} */ #ifdef DBUS_BUILD_TESTS diff --git a/dbus/dbus-marshal-header.h b/dbus/dbus-marshal-header.h index fed2888b..837c937b 100644 --- a/dbus/dbus-marshal-header.h +++ b/dbus/dbus-marshal-header.h @@ -125,7 +125,8 @@ dbus_bool_t _dbus_header_load (DBusHeader *header, const DBusString *str, int start, int len); - +void _dbus_header_byteswap (DBusHeader *header, + int new_order); diff --git a/dbus/dbus-marshal-recursive-util.c b/dbus/dbus-marshal-recursive-util.c index 493672b6..08d030ab 100644 --- a/dbus/dbus-marshal-recursive-util.c +++ b/dbus/dbus-marshal-recursive-util.c @@ -21,11 +21,108 @@ * */ +#include + +#ifdef DBUS_BUILD_TESTS + #include "dbus-marshal-recursive.h" #include "dbus-marshal-basic.h" #include "dbus-internals.h" +#include -#ifdef DBUS_BUILD_TESTS +static void +basic_value_zero (DBusBasicValue *value) +{ + +#ifdef DBUS_HAVE_INT64 + value->u64 = 0; +#else + value->u64.first32 = 0; + value->u64.second32 = 0; +#endif +} + +static dbus_bool_t +basic_value_equal (int type, + DBusBasicValue *lhs, + DBusBasicValue *rhs) +{ + if (type == DBUS_TYPE_STRING || + type == DBUS_TYPE_SIGNATURE || + type == DBUS_TYPE_OBJECT_PATH) + { + return strcmp (lhs->str, rhs->str) == 0; + } + else + { +#ifdef DBUS_HAVE_INT64 + return lhs->u64 == rhs->u64; +#else + return lhs->u64.first32 == rhs->u64.first32 && + lhs->u64.second32 == rhs->u64.second32; +#endif + } +} + +static dbus_bool_t +equal_values_helper (DBusTypeReader *lhs, + DBusTypeReader *rhs) +{ + int lhs_type; + int rhs_type; + + lhs_type = _dbus_type_reader_get_current_type (lhs); + rhs_type = _dbus_type_reader_get_current_type (rhs); + + if (lhs_type != rhs_type) + return FALSE; + + if (lhs_type == DBUS_TYPE_INVALID) + return TRUE; + + if (_dbus_type_is_basic (lhs_type)) + { + DBusBasicValue lhs_value; + DBusBasicValue rhs_value; + + basic_value_zero (&lhs_value); + basic_value_zero (&rhs_value); + + _dbus_type_reader_read_basic (lhs, &lhs_value); + _dbus_type_reader_read_basic (rhs, &rhs_value); + + return basic_value_equal (lhs_type, &lhs_value, &rhs_value); + } + else + { + DBusTypeReader lhs_sub; + DBusTypeReader rhs_sub; + + _dbus_type_reader_recurse (lhs, &lhs_sub); + _dbus_type_reader_recurse (rhs, &rhs_sub); + + return equal_values_helper (&lhs_sub, &rhs_sub); + } +} + +/** + * See whether the two readers point to identical data blocks. + * + * @param lhs reader 1 + * @param rhs reader 2 + * @returns #TRUE if the data blocks have the same values + */ +dbus_bool_t +_dbus_type_reader_equal_values (const DBusTypeReader *lhs, + const DBusTypeReader *rhs) +{ + DBusTypeReader copy_lhs = *lhs; + DBusTypeReader copy_rhs = *rhs; + + return equal_values_helper (©_lhs, ©_rhs); +} + +/* TESTS */ #include "dbus-test.h" #include "dbus-list.h" #include diff --git a/dbus/dbus-marshal-recursive.h b/dbus/dbus-marshal-recursive.h index 2e8317f4..45deeb5c 100644 --- a/dbus/dbus-marshal-recursive.h +++ b/dbus/dbus-marshal-recursive.h @@ -27,7 +27,6 @@ #include #include #include -#include /* this can vanish when we merge */ #ifndef PACKAGE #error "config.h not included here" @@ -168,6 +167,9 @@ dbus_bool_t _dbus_type_reader_delete (DBusTypeReader * dbus_bool_t _dbus_type_reader_greater_than (const DBusTypeReader *lhs, const DBusTypeReader *rhs); +dbus_bool_t _dbus_type_reader_equal_values (const DBusTypeReader *lhs, + const DBusTypeReader *rhs); + void _dbus_type_writer_init (DBusTypeWriter *writer, int byte_order, DBusString *type_str, diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c index e06add50..f15d2811 100644 --- a/dbus/dbus-marshal-validate.c +++ b/dbus/dbus-marshal-validate.c @@ -24,6 +24,8 @@ #include "dbus-internals.h" #include "dbus-marshal-validate.h" #include "dbus-marshal-recursive.h" +#include "dbus-marshal-basic.h" +#include "dbus-string.h" /** * @addtogroup DBusMarshal @@ -254,6 +256,11 @@ validate_body_helper (DBusTypeReader *reader, while (p < array_end) { + /* FIXME we are calling a function per array element! very bad + * need if (dbus_type_is_fixed(elem_type)) here to just skip + * big blocks of ints/bytes/etc. + */ + validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p); if (validity != DBUS_VALID) return validity; diff --git a/dbus/dbus-marshal-validate.h b/dbus/dbus-marshal-validate.h index 195f46da..94b77989 100644 --- a/dbus/dbus-marshal-validate.h +++ b/dbus/dbus-marshal-validate.h @@ -25,7 +25,6 @@ #define DBUS_MARSHAL_VALIDATE_H #include -#include #ifndef PACKAGE #error "config.h not included here" diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index cf15109b..38ae317a 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -25,6 +25,7 @@ #include "dbus-internals.h" #include "dbus-marshal-recursive.h" #include "dbus-marshal-validate.h" +#include "dbus-marshal-byteswap.h" #include "dbus-marshal-header.h" #include "dbus-message-private.h" #include "dbus-object-tree.h" @@ -76,6 +77,57 @@ struct DBusMessageRealIter } u; /**< the type writer or reader that does all the work */ }; +static void +get_const_signature (DBusHeader *header, + const DBusString **type_str_p, + int *type_pos_p) +{ + if (_dbus_header_get_field_raw (header, + DBUS_HEADER_FIELD_SIGNATURE, + type_str_p, + type_pos_p)) + { + *type_pos_p += 1; /* skip the signature length which is 1 byte */ + } + else + { + *type_str_p = &_dbus_empty_signature_str; + *type_pos_p = 0; + } +} + +/** + * Swaps the message to compiler byte order if required + * + * @param message the message + */ +static void +_dbus_message_byteswap (DBusMessage *message) +{ + const DBusString *type_str; + int type_pos; + + if (message->byte_order == DBUS_COMPILER_BYTE_ORDER) + return; + + _dbus_verbose ("Swapping message into compiler byte order\n"); + + get_const_signature (&message->header, &type_str, &type_pos); + + _dbus_marshal_byteswap (type_str, type_pos, + message->byte_order, + DBUS_COMPILER_BYTE_ORDER, + &message->body, 0); + + message->byte_order = DBUS_COMPILER_BYTE_ORDER; + + _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER); +} + +#define ensure_byte_order(message) \ + if (message->byte_order != DBUS_COMPILER_BYTE_ORDER) \ + _dbus_message_byteswap (message) + /** * Gets the data to be sent over the network for this message. * The header and then the body should be written out. @@ -250,25 +302,6 @@ set_or_delete_string_field (DBusMessage *message, &value); } -static void -get_const_signature (DBusHeader *header, - const DBusString **type_str_p, - int *type_pos_p) -{ - if (_dbus_header_get_field_raw (header, - DBUS_HEADER_FIELD_SIGNATURE, - type_str_p, - type_pos_p)) - { - *type_pos_p += 1; /* skip the signature length which is 1 byte */ - } - else - { - *type_str_p = &_dbus_empty_signature_str; - *type_pos_p = 0; - } -} - #if 0 /* Probably we don't need to use this */ /** @@ -1345,6 +1378,11 @@ _dbus_message_iter_init_common (DBusMessage *message, { _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter)); + /* Since the iterator will read or write who-knows-what from the + * message, we need to get in the right byte order + */ + ensure_byte_order (message); + real->message = message; real->changed_stamp = message->changed_stamp; real->iter_type = iter_type; @@ -1401,6 +1439,8 @@ _dbus_message_iter_check (DBusMessageRealIter *iter) _dbus_warn ("dbus message changed byte order since iterator was created\n"); return FALSE; } + /* because we swap the message into compiler order when you init an iter */ + _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER); } else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER) { @@ -1409,6 +1449,8 @@ _dbus_message_iter_check (DBusMessageRealIter *iter) _dbus_warn ("dbus message changed byte order since append iterator was created\n"); return FALSE; } + /* because we swap the message into compiler order when you init an iter */ + _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER); } else { diff --git a/dbus/dbus-test.c b/dbus/dbus-test.c index 5f51832c..eb2b8787 100644 --- a/dbus/dbus-test.c +++ b/dbus/dbus-test.c @@ -128,6 +128,12 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir) _dbus_warn ("recursive marshal tests disabled\n"); #endif + printf ("%s: running byteswap tests\n", "dbus-test"); + if (!_dbus_marshal_byteswap_test ()) + die ("byteswap marshaled data"); + + check_memleaks (); + printf ("%s: running memory tests\n", "dbus-test"); if (!_dbus_memory_test ()) die ("memory"); diff --git a/dbus/dbus-test.h b/dbus/dbus-test.h index 9a63914f..3a87afb1 100644 --- a/dbus/dbus-test.h +++ b/dbus/dbus-test.h @@ -33,6 +33,7 @@ dbus_bool_t _dbus_dict_test (void); dbus_bool_t _dbus_list_test (void); dbus_bool_t _dbus_marshal_test (void); dbus_bool_t _dbus_marshal_recursive_test (void); +dbus_bool_t _dbus_marshal_byteswap_test (void); dbus_bool_t _dbus_marshal_header_test (void); dbus_bool_t _dbus_marshal_validate_test (void); dbus_bool_t _dbus_mem_pool_test (void); -- cgit