00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025 #include "dbus-marshal-byteswap.h"
00026 #include "dbus-marshal-basic.h"
00027 #include "dbus-signature.h"
00028
00034 static void
00035 byteswap_body_helper (DBusTypeReader *reader,
00036 dbus_bool_t walk_reader_to_end,
00037 int old_byte_order,
00038 int new_byte_order,
00039 unsigned char *p,
00040 unsigned char **new_p)
00041 {
00042 int current_type;
00043
00044 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
00045 {
00046 switch (current_type)
00047 {
00048 case DBUS_TYPE_BYTE:
00049 ++p;
00050 break;
00051
00052 case DBUS_TYPE_INT16:
00053 case DBUS_TYPE_UINT16:
00054 {
00055 p = _DBUS_ALIGN_ADDRESS (p, 2);
00056 *((dbus_uint16_t*)p) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)p));
00057 p += 2;
00058 }
00059 break;
00060
00061 case DBUS_TYPE_BOOLEAN:
00062 case DBUS_TYPE_INT32:
00063 case DBUS_TYPE_UINT32:
00064 {
00065 p = _DBUS_ALIGN_ADDRESS (p, 4);
00066 *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p));
00067 p += 4;
00068 }
00069 break;
00070
00071 case DBUS_TYPE_INT64:
00072 case DBUS_TYPE_UINT64:
00073 case DBUS_TYPE_DOUBLE:
00074 {
00075 p = _DBUS_ALIGN_ADDRESS (p, 8);
00076 #ifdef DBUS_HAVE_INT64
00077 *((dbus_uint64_t*)p) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)p));
00078 #else
00079 _dbus_swap_array (p, 1, 8);
00080 #endif
00081 p += 8;
00082 }
00083 break;
00084
00085 case DBUS_TYPE_ARRAY:
00086 case DBUS_TYPE_STRING:
00087 case DBUS_TYPE_OBJECT_PATH:
00088 {
00089 dbus_uint32_t array_len;
00090
00091 p = _DBUS_ALIGN_ADDRESS (p, 4);
00092
00093 array_len = _dbus_unpack_uint32 (old_byte_order, p);
00094
00095 *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p));
00096 p += 4;
00097
00098 if (current_type == DBUS_TYPE_ARRAY)
00099 {
00100 int elem_type;
00101 int alignment;
00102
00103 elem_type = _dbus_type_reader_get_element_type (reader);
00104 alignment = _dbus_type_get_alignment (elem_type);
00105
00106 _dbus_assert ((array_len / alignment) < DBUS_MAXIMUM_ARRAY_LENGTH);
00107
00108 p = _DBUS_ALIGN_ADDRESS (p, alignment);
00109
00110 if (dbus_type_is_fixed (elem_type))
00111 {
00112 if (alignment > 1)
00113 _dbus_swap_array (p, array_len / alignment, alignment);
00114 p += array_len;
00115 }
00116 else
00117 {
00118 DBusTypeReader sub;
00119 const unsigned char *array_end;
00120
00121 array_end = p + array_len;
00122
00123 _dbus_type_reader_recurse (reader, &sub);
00124
00125 while (p < array_end)
00126 {
00127 byteswap_body_helper (&sub,
00128 FALSE,
00129 old_byte_order,
00130 new_byte_order,
00131 p, &p);
00132 }
00133 }
00134 }
00135 else
00136 {
00137 _dbus_assert (current_type == DBUS_TYPE_STRING ||
00138 current_type == DBUS_TYPE_OBJECT_PATH);
00139
00140 p += (array_len + 1);
00141 }
00142 }
00143 break;
00144
00145 case DBUS_TYPE_SIGNATURE:
00146 {
00147 dbus_uint32_t sig_len;
00148
00149 sig_len = *p;
00150
00151 p += (sig_len + 2);
00152 }
00153 break;
00154
00155 case DBUS_TYPE_VARIANT:
00156 {
00157
00158
00159
00160 dbus_uint32_t sig_len;
00161 DBusString sig;
00162 DBusTypeReader sub;
00163 int contained_alignment;
00164
00165 sig_len = *p;
00166 ++p;
00167
00168 _dbus_string_init_const_len (&sig, p, sig_len);
00169
00170 p += (sig_len + 1);
00171
00172 contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (&sig, 0));
00173
00174 p = _DBUS_ALIGN_ADDRESS (p, contained_alignment);
00175
00176 _dbus_type_reader_init_types_only (&sub, &sig, 0);
00177
00178 byteswap_body_helper (&sub, FALSE, old_byte_order, new_byte_order, p, &p);
00179 }
00180 break;
00181
00182 case DBUS_TYPE_STRUCT:
00183 case DBUS_TYPE_DICT_ENTRY:
00184 {
00185 DBusTypeReader sub;
00186
00187 p = _DBUS_ALIGN_ADDRESS (p, 8);
00188
00189 _dbus_type_reader_recurse (reader, &sub);
00190
00191 byteswap_body_helper (&sub, TRUE, old_byte_order, new_byte_order, p, &p);
00192 }
00193 break;
00194
00195 case DBUS_TYPE_UNIX_FD:
00196
00197 _dbus_assert_not_reached("attempted to byteswap unix fds which makes no sense");
00198 break;
00199
00200 default:
00201 _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature");
00202 break;
00203 }
00204
00205 if (walk_reader_to_end)
00206 _dbus_type_reader_next (reader);
00207 else
00208 break;
00209 }
00210
00211 if (new_p)
00212 *new_p = p;
00213 }
00214
00225 void
00226 _dbus_marshal_byteswap (const DBusString *signature,
00227 int signature_start,
00228 int old_byte_order,
00229 int new_byte_order,
00230 DBusString *value_str,
00231 int value_pos)
00232 {
00233 DBusTypeReader reader;
00234
00235 _dbus_assert (value_pos >= 0);
00236 _dbus_assert (value_pos <= _dbus_string_get_length (value_str));
00237
00238 if (old_byte_order == new_byte_order)
00239 return;
00240
00241 _dbus_type_reader_init_types_only (&reader,
00242 signature, signature_start);
00243
00244 byteswap_body_helper (&reader, TRUE,
00245 old_byte_order, new_byte_order,
00246 _dbus_string_get_data_len (value_str, value_pos, 0),
00247 NULL);
00248 }
00249
00252