1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-marshal.c Marshalling routines
4 * Copyright (C) 2002 CodeFactory AB
5 * Copyright (C) 2003 Red Hat, Inc.
7 * Licensed under the Academic Free License version 1.2
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "dbus-marshal.h"
26 #include "dbus-internals.h"
27 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
28 #include "dbus-string-private.h"
33 * @defgroup DBusMarshal marshaling and unmarshaling
34 * @ingroup DBusInternals
35 * @brief functions to marshal/unmarshal data from the wire
37 * Types and functions related to converting primitive data types from
38 * wire format to native machine format, and vice versa.
44 unpack_4_octets (int byte_order,
45 const unsigned char *data)
47 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
49 if (byte_order == DBUS_LITTLE_ENDIAN)
50 return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
52 return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
55 #ifndef DBUS_HAVE_INT64
58 swap_bytes (unsigned char *data,
61 unsigned char *p1 = data;
62 unsigned char *p2 = data + len - 1;
66 unsigned char tmp = *p1;
74 #endif /* !DBUS_HAVE_INT64 */
78 #ifdef DBUS_HAVE_INT64
86 unpack_8_octets (int byte_order,
87 const unsigned char *data)
91 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
92 _dbus_assert (sizeof (r) == 8);
94 #ifdef DBUS_HAVE_INT64
95 if (byte_order == DBUS_LITTLE_ENDIAN)
96 r.u = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
98 r.u = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
100 r.d = *(double*)data;
101 swap_bytes (&r, sizeof (r));
108 * Unpacks a 32 bit unsigned integer from a data pointer
110 * @param byte_order The byte order to use
111 * @param data the data pointer
112 * @returns the integer
115 _dbus_unpack_uint32 (int byte_order,
116 const unsigned char *data)
118 return unpack_4_octets (byte_order, data);
122 * Unpacks a 32 bit signed integer from a data pointer
124 * @param byte_order The byte order to use
125 * @param data the data pointer
126 * @returns the integer
129 _dbus_unpack_int32 (int byte_order,
130 const unsigned char *data)
132 return (dbus_int32_t) unpack_4_octets (byte_order, data);
135 #ifdef DBUS_HAVE_INT64
137 * Unpacks a 64 bit unsigned integer from a data pointer
139 * @param byte_order The byte order to use
140 * @param data the data pointer
141 * @returns the integer
144 _dbus_unpack_uint64 (int byte_order,
145 const unsigned char *data)
149 r = unpack_8_octets (byte_order, data);
155 * Unpacks a 64 bit signed integer from a data pointer
157 * @param byte_order The byte order to use
158 * @param data the data pointer
159 * @returns the integer
162 _dbus_unpack_int64 (int byte_order,
163 const unsigned char *data)
167 r = unpack_8_octets (byte_order, data);
172 #endif /* DBUS_HAVE_INT64 */
175 pack_4_octets (dbus_uint32_t value,
179 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
181 if ((byte_order) == DBUS_LITTLE_ENDIAN)
182 *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
184 *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
188 pack_8_octets (DBusOctets8 value,
192 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
194 #ifdef DBUS_HAVE_INT64
195 if ((byte_order) == DBUS_LITTLE_ENDIAN)
196 *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u);
198 *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u);
200 memcpy (data, &value, 8);
201 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
202 swap_bytes ((unsigned char *)data, 8);
207 * Packs a 32 bit unsigned integer into a data pointer.
209 * @param value the value
210 * @param byte_order the byte order to use
211 * @param data the data pointer
214 _dbus_pack_uint32 (dbus_uint32_t value,
218 pack_4_octets (value, byte_order, data);
222 * Packs a 32 bit signed integer into a data pointer.
224 * @param value the value
225 * @param byte_order the byte order to use
226 * @param data the data pointer
229 _dbus_pack_int32 (dbus_int32_t value,
233 pack_4_octets ((dbus_uint32_t) value, byte_order, data);
236 #ifdef DBUS_HAVE_INT64
238 * Packs a 64 bit unsigned integer into a data pointer.
240 * @param value the value
241 * @param byte_order the byte order to use
242 * @param data the data pointer
245 _dbus_pack_uint64 (dbus_uint64_t value,
251 pack_8_octets (r, byte_order, data);
255 * Packs a 64 bit signed integer into a data pointer.
257 * @param value the value
258 * @param byte_order the byte order to use
259 * @param data the data pointer
262 _dbus_pack_int64 (dbus_int64_t value,
268 pack_8_octets (r, byte_order, data);
270 #endif /* DBUS_HAVE_INT64 */
273 set_4_octets (DBusString *str,
280 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
281 byte_order == DBUS_BIG_ENDIAN);
283 data = _dbus_string_get_data_len (str, offset, 4);
285 _dbus_pack_uint32 (value, byte_order, data);
289 set_8_octets (DBusString *str,
296 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
297 byte_order == DBUS_BIG_ENDIAN);
299 data = _dbus_string_get_data_len (str, offset, 8);
301 pack_8_octets (value, byte_order, data);
305 * Sets the 4 bytes at the given offset to a marshaled signed integer,
306 * replacing anything found there previously.
308 * @param str the string to write the marshalled int to
309 * @param offset the byte offset where int should be written
310 * @param byte_order the byte order to use
311 * @param value the value
315 _dbus_marshal_set_int32 (DBusString *str,
320 set_4_octets (str, byte_order, offset, (dbus_uint32_t) value);
324 * Sets the 4 bytes at the given offset to a marshaled unsigned
325 * integer, replacing anything found there previously.
327 * @param str the string to write the marshalled int to
328 * @param offset the byte offset where int should be written
329 * @param byte_order the byte order to use
330 * @param value the value
334 _dbus_marshal_set_uint32 (DBusString *str,
339 set_4_octets (str, byte_order, offset, value);
342 #ifdef DBUS_HAVE_INT64
345 * Sets the 4 bytes at the given offset to a marshaled signed integer,
346 * replacing anything found there previously.
348 * @param str the string to write the marshalled int to
349 * @param offset the byte offset where int should be written
350 * @param byte_order the byte order to use
351 * @param value the value
355 _dbus_marshal_set_int64 (DBusString *str,
362 set_8_octets (str, byte_order, offset, r);
366 * Sets the 4 bytes at the given offset to a marshaled unsigned
367 * integer, replacing anything found there previously.
369 * @param str the string to write the marshalled int to
370 * @param offset the byte offset where int should be written
371 * @param byte_order the byte order to use
372 * @param value the value
376 _dbus_marshal_set_uint64 (DBusString *str,
383 set_8_octets (str, byte_order, offset, r);
385 #endif /* DBUS_HAVE_INT64 */
388 * Sets the existing marshaled string at the given offset with
389 * a new marshaled string. The given offset must point to
390 * an existing string or the wrong length will be deleted
391 * and replaced with the new string.
393 * @param str the string to write the marshalled string to
394 * @param offset the byte offset where string should be written
395 * @param byte_order the byte order to use
396 * @param value the value
397 * @param len the length to use
398 * @returns #TRUE on success
402 _dbus_marshal_set_string (DBusString *str,
405 const DBusString *value,
410 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
411 byte_order == DBUS_BIG_ENDIAN);
413 old_len = _dbus_demarshal_uint32 (str, byte_order,
416 if (!_dbus_string_replace_len (value, 0, len,
417 str, offset + 4, old_len))
420 _dbus_marshal_set_uint32 (str, byte_order,
427 marshal_4_octets (DBusString *str,
431 _dbus_assert (sizeof (value) == 4);
433 if (!_dbus_string_align_length (str, sizeof (dbus_uint32_t)))
436 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
437 value = DBUS_UINT32_SWAP_LE_BE (value);
439 return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_uint32_t));
443 marshal_8_octets (DBusString *str,
447 _dbus_assert (sizeof (value) == 8);
449 if (!_dbus_string_align_length (str, 8))
452 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
453 pack_8_octets (value, byte_order, (unsigned char*) &value); /* pack into self, swapping as we go */
455 return _dbus_string_append_len (str, (const char *)&value, 8);
459 * Marshals a double value.
461 * @param str the string to append the marshalled value to
462 * @param byte_order the byte order to use
463 * @param value the value
464 * @returns #TRUE on success
467 _dbus_marshal_double (DBusString *str,
473 return marshal_8_octets (str, byte_order, r);
477 * Marshals a 32 bit signed integer value.
479 * @param str the string to append the marshalled value to
480 * @param byte_order the byte order to use
481 * @param value the value
482 * @returns #TRUE on success
485 _dbus_marshal_int32 (DBusString *str,
489 return marshal_4_octets (str, byte_order, (dbus_uint32_t) value);
493 * Marshals a 32 bit unsigned integer value.
495 * @param str the string to append the marshalled value to
496 * @param byte_order the byte order to use
497 * @param value the value
498 * @returns #TRUE on success
501 _dbus_marshal_uint32 (DBusString *str,
505 return marshal_4_octets (str, byte_order, value);
509 #ifdef DBUS_HAVE_INT64
511 * Marshals a 64 bit signed integer value.
513 * @param str the string to append the marshalled value to
514 * @param byte_order the byte order to use
515 * @param value the value
516 * @returns #TRUE on success
519 _dbus_marshal_int64 (DBusString *str,
525 return marshal_8_octets (str, byte_order, r);
529 * Marshals a 64 bit unsigned integer value.
531 * @param str the string to append the marshalled value to
532 * @param byte_order the byte order to use
533 * @param value the value
534 * @returns #TRUE on success
537 _dbus_marshal_uint64 (DBusString *str,
543 return marshal_8_octets (str, byte_order, r);
546 #endif /* DBUS_HAVE_INT64 */
549 * Marshals a UTF-8 string
551 * @todo: If the string append fails we need to restore
552 * the old length. (also for other marshallers)
554 * @param str the string to append the marshalled value to
555 * @param byte_order the byte order to use
556 * @param value the string
557 * @returns #TRUE on success
560 _dbus_marshal_string (DBusString *str,
564 int len, old_string_len;
566 old_string_len = _dbus_string_get_length (str);
568 len = strlen (value);
570 if (!_dbus_marshal_uint32 (str, byte_order, len))
572 /* Restore the previous length */
573 _dbus_string_set_length (str, old_string_len);
578 return _dbus_string_append_len (str, value, len + 1);
582 * Marshals a byte array
584 * @param str the string to append the marshalled value to
585 * @param byte_order the byte order to use
586 * @param value the array
587 * @param len number of elements in the array
588 * @returns #TRUE on success
591 _dbus_marshal_byte_array (DBusString *str,
593 const unsigned char *value,
598 old_string_len = _dbus_string_get_length (str);
600 if (!_dbus_marshal_uint32 (str, byte_order, len))
602 /* Restore the previous length */
603 _dbus_string_set_length (str, old_string_len);
611 return _dbus_string_append_len (str, value, len);
615 marshal_4_octets_array (DBusString *str,
617 const dbus_uint32_t *value,
623 old_string_len = _dbus_string_get_length (str);
625 if (!_dbus_marshal_uint32 (str, byte_order, len * 4))
628 array_start = _dbus_string_get_length (str);
630 if (!_dbus_string_append_len (str, (const unsigned char*) value,
634 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
636 const unsigned char *d;
637 const unsigned char *end;
639 d = _dbus_string_get_data (str) + array_start;
643 *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
651 /* Restore previous length */
652 _dbus_string_set_length (str, old_string_len);
658 marshal_8_octets_array (DBusString *str,
660 const DBusOctets8 *value,
666 old_string_len = _dbus_string_get_length (str);
668 if (!_dbus_marshal_uint32 (str, byte_order, len * 8))
671 array_start = _dbus_string_get_length (str);
673 if (!_dbus_string_append_len (str, (const unsigned char*) value,
677 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
679 const unsigned char *d;
680 const unsigned char *end;
682 d = _dbus_string_get_data (str) + array_start;
686 #ifdef DBUS_HAVE_INT64
687 *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
698 /* Restore previous length */
699 _dbus_string_set_length (str, old_string_len);
705 * Marshals a 32 bit signed integer array
707 * @param str the string to append the marshalled value to
708 * @param byte_order the byte order to use
709 * @param value the array
710 * @param len the length of the array
711 * @returns #TRUE on success
714 _dbus_marshal_int32_array (DBusString *str,
716 const dbus_int32_t *value,
719 return marshal_4_octets_array (str, byte_order,
720 (const dbus_uint32_t*) value,
725 * Marshals a 32 bit unsigned integer array
727 * @param str the string to append the marshalled value to
728 * @param byte_order the byte order to use
729 * @param value the array
730 * @param len the length of the array
731 * @returns #TRUE on success
734 _dbus_marshal_uint32_array (DBusString *str,
736 const dbus_uint32_t *value,
739 return marshal_4_octets_array (str, byte_order,
744 #ifdef DBUS_HAVE_INT64
747 * Marshals a 64 bit signed integer array
749 * @param str the string to append the marshalled value to
750 * @param byte_order the byte order to use
751 * @param value the array
752 * @param len the length of the array
753 * @returns #TRUE on success
756 _dbus_marshal_int64_array (DBusString *str,
758 const dbus_int64_t *value,
761 return marshal_8_octets_array (str, byte_order,
762 (const DBusOctets8*) value,
767 * Marshals a 64 bit unsigned integer array
769 * @param str the string to append the marshalled value to
770 * @param byte_order the byte order to use
771 * @param value the array
772 * @param len the length of the array
773 * @returns #TRUE on success
776 _dbus_marshal_uint64_array (DBusString *str,
778 const dbus_uint64_t *value,
781 return marshal_8_octets_array (str, byte_order,
782 (const DBusOctets8*) value,
786 #endif /* DBUS_HAVE_INT64 */
789 * Marshals a double array
791 * @param str the string to append the marshalled value to
792 * @param byte_order the byte order to use
793 * @param value the array
794 * @param len the length of the array
795 * @returns #TRUE on success
798 _dbus_marshal_double_array (DBusString *str,
803 return marshal_8_octets_array (str, byte_order,
804 (const DBusOctets8*) value,
809 * Marshals a string array
811 * @param str the string to append the marshalled value to
812 * @param byte_order the byte order to use
813 * @param value the array
814 * @param len the length of the array
815 * @returns #TRUE on success
818 _dbus_marshal_string_array (DBusString *str,
823 int i, old_string_len, array_start;
825 old_string_len = _dbus_string_get_length (str);
827 /* Set the length to 0 temporarily */
828 if (!_dbus_marshal_uint32 (str, byte_order, 0))
831 array_start = _dbus_string_get_length (str);
833 for (i = 0; i < len; i++)
834 if (!_dbus_marshal_string (str, byte_order, value[i]))
837 /* Write the length now that we know it */
838 _dbus_marshal_set_uint32 (str, byte_order,
839 _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
840 _dbus_string_get_length (str) - array_start);
845 /* Restore previous length */
846 _dbus_string_set_length (str, old_string_len);
852 demarshal_4_octets (const DBusString *str,
857 const DBusRealString *real = (const DBusRealString*) str;
859 pos = _DBUS_ALIGN_VALUE (pos, 4);
864 return unpack_4_octets (byte_order, real->str + pos);
868 demarshal_8_octets (const DBusString *str,
873 const DBusRealString *real = (const DBusRealString*) str;
875 pos = _DBUS_ALIGN_VALUE (pos, 8);
880 return unpack_8_octets (byte_order, real->str + pos);
884 * Demarshals a double.
886 * @param str the string containing the data
887 * @param byte_order the byte order
888 * @param pos the position in the string
889 * @param new_pos the new position of the string
890 * @returns the demarshaled double.
893 _dbus_demarshal_double (const DBusString *str,
900 r = demarshal_8_octets (str, byte_order, pos, new_pos);
906 * Demarshals a 32 bit signed integer.
908 * @param str the string containing the data
909 * @param byte_order the byte order
910 * @param pos the position in the string
911 * @param new_pos the new position of the string
912 * @returns the demarshaled integer.
915 _dbus_demarshal_int32 (const DBusString *str,
920 return (dbus_int32_t) demarshal_4_octets (str, byte_order, pos, new_pos);
924 * Demarshals a 32 bit unsigned integer.
926 * @param str the string containing the data
927 * @param byte_order the byte order
928 * @param pos the position in the string
929 * @param new_pos the new position of the string
930 * @returns the demarshaled integer.
933 _dbus_demarshal_uint32 (const DBusString *str,
938 return demarshal_4_octets (str, byte_order, pos, new_pos);
941 #ifdef DBUS_HAVE_INT64
944 * Demarshals a 64 bit signed integer.
946 * @param str the string containing the data
947 * @param byte_order the byte order
948 * @param pos the position in the string
949 * @param new_pos the new position of the string
950 * @returns the demarshaled integer.
953 _dbus_demarshal_int64 (const DBusString *str,
960 r = demarshal_8_octets (str, byte_order, pos, new_pos);
966 * Demarshals a 64 bit unsigned integer.
968 * @param str the string containing the data
969 * @param byte_order the byte order
970 * @param pos the position in the string
971 * @param new_pos the new position of the string
972 * @returns the demarshaled integer.
975 _dbus_demarshal_uint64 (const DBusString *str,
982 r = demarshal_8_octets (str, byte_order, pos, new_pos);
987 #endif /* DBUS_HAVE_INT64 */
990 * Demarshals an UTF-8 string.
992 * @todo Should we check the string to make sure
993 * that it's valid UTF-8, and maybe "fix" the string
996 * @todo Should probably demarshal to a DBusString,
997 * having memcpy() in here is Evil(tm).
999 * @param str the string containing the data
1000 * @param byte_order the byte order
1001 * @param pos the position in the string
1002 * @param new_pos the new position of the string
1003 * @returns the demarshaled string.
1006 _dbus_demarshal_string (const DBusString *str,
1015 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1017 retval = dbus_malloc (len + 1);
1022 data = _dbus_string_get_const_data_len (str, pos, len + 1);
1027 memcpy (retval, data, len + 1);
1030 *new_pos = pos + len + 1;
1036 * Demarshals a byte array.
1038 * @todo Should probably demarshal to a DBusString,
1039 * having memcpy() in here is Evil(tm).
1041 * @param str the string containing the data
1042 * @param byte_order the byte order
1043 * @param pos the position in the string
1044 * @param new_pos the new position of the string
1045 * @param array the array
1046 * @param array_len length of the demarshaled data
1048 * @returns #TRUE on success
1051 _dbus_demarshal_byte_array (const DBusString *str,
1055 unsigned char **array,
1059 unsigned char *retval;
1062 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1075 retval = dbus_malloc (len);
1080 data = _dbus_string_get_const_data_len (str, pos, len);
1088 memcpy (retval, data, len);
1091 *new_pos = pos + len;
1100 demarshal_4_octets_array (const DBusString *str,
1104 dbus_uint32_t **array,
1108 dbus_uint32_t *retval;
1111 byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1125 if (!_dbus_string_copy_data_len (str, (char**) &retval,
1129 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1131 for (i = 0; i < len; i++)
1132 retval[i] = DBUS_UINT32_SWAP_LE_BE (retval[i]);
1136 *new_pos = pos + byte_len;
1145 demarshal_8_octets_array (const DBusString *str,
1149 DBusOctets8 **array,
1153 DBusOctets8 *retval;
1156 byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1170 if (!_dbus_string_copy_data_len (str, (char**) &retval,
1174 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1176 for (i = 0; i < len; i++)
1178 #ifdef DBUS_HAVE_INT64
1179 retval[i].u = DBUS_UINT64_SWAP_LE_BE (retval[i].u);
1181 swap_bytes (&retval[i], 8);
1187 *new_pos = pos + byte_len;
1196 * Demarshals a 32 bit signed integer array.
1198 * @param str the string containing the data
1199 * @param byte_order the byte order
1200 * @param pos the position in the string
1201 * @param new_pos the new position of the string
1202 * @param array the array
1203 * @param array_len length of the demarshaled data
1204 * @returns #TRUE on success
1207 _dbus_demarshal_int32_array (const DBusString *str,
1211 dbus_int32_t **array,
1214 return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1215 (dbus_uint32_t**) array, array_len);
1219 * Demarshals a 32 bit unsigned integer array.
1221 * @param str the string containing the data
1222 * @param byte_order the byte order
1223 * @param pos the position in the string
1224 * @param new_pos the new position of the string
1225 * @param array the array
1226 * @param array_len length of the demarshaled data
1227 * @returns #TRUE on success
1230 _dbus_demarshal_uint32_array (const DBusString *str,
1234 dbus_uint32_t **array,
1237 return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1241 #ifdef DBUS_HAVE_INT64
1244 * Demarshals a 64 bit signed integer array.
1246 * @param str the string containing the data
1247 * @param byte_order the byte order
1248 * @param pos the position in the string
1249 * @param new_pos the new position of the string
1250 * @param array the array
1251 * @param array_len length of the demarshaled data
1252 * @returns #TRUE on success
1255 _dbus_demarshal_int64_array (const DBusString *str,
1259 dbus_int64_t **array,
1262 return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1263 (DBusOctets8**) array, array_len);
1267 * Demarshals a 64 bit unsigned integer array.
1269 * @param str the string containing the data
1270 * @param byte_order the byte order
1271 * @param pos the position in the string
1272 * @param new_pos the new position of the string
1273 * @param array the array
1274 * @param array_len length of the demarshaled data
1275 * @returns #TRUE on success
1278 _dbus_demarshal_uint64_array (const DBusString *str,
1282 dbus_uint64_t **array,
1285 return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1286 (DBusOctets8**) array, array_len);
1289 #endif /* DBUS_HAVE_INT64 */
1292 * Demarshals a double array.
1294 * @param str the string containing the data
1295 * @param byte_order the byte order
1296 * @param pos the position in the string
1297 * @param new_pos the new position of the string
1298 * @param array the array
1299 * @param array_len length of the demarshaled data
1300 * @returns #TRUE on success
1303 _dbus_demarshal_double_array (const DBusString *str,
1310 return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1311 (DBusOctets8**) array, array_len);
1315 * Demarshals a string array.
1317 * @param str the string containing the data
1318 * @param byte_order the byte order
1319 * @param pos the position in the string
1320 * @param new_pos the new position of the string
1321 * @param array the array
1322 * @param array_len length of the demarshaled data
1323 * @returns #TRUE on success
1326 _dbus_demarshal_string_array (const DBusString *str,
1336 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1349 retval = dbus_new (char *, len + 1);
1356 for (i = 0; i < len; i++)
1358 retval[i] = _dbus_demarshal_string (str, byte_order, pos, &pos);
1373 for (j = 0; j < i; j++)
1374 dbus_free (retval[i]);
1381 * Returns the position right after the end of an argument. PERFORMS
1382 * NO VALIDATION WHATSOEVER. The message must have been previously
1385 * @param str a string
1386 * @param byte_order the byte order to use
1387 * @param type the type of the argument
1388 * @param pos the pos where the arg starts
1389 * @param end_pos pointer where the position right
1390 * after the end position will follow
1391 * @returns TRUE if more data exists after the arg
1394 _dbus_marshal_get_arg_end_pos (const DBusString *str,
1400 if (pos >= _dbus_string_get_length (str))
1405 case DBUS_TYPE_INVALID:
1413 case DBUS_TYPE_BYTE:
1417 case DBUS_TYPE_BOOLEAN:
1421 case DBUS_TYPE_INT32:
1422 *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
1426 case DBUS_TYPE_UINT32:
1427 *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
1431 #ifdef DBUS_HAVE_INT64
1432 case DBUS_TYPE_INT64:
1433 *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int64_t)) + sizeof (dbus_int64_t);
1437 case DBUS_TYPE_UINT64:
1438 *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint64_t)) + sizeof (dbus_uint64_t);
1441 #endif /* DBUS_HAVE_INT64 */
1443 case DBUS_TYPE_DOUBLE:
1444 *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (double)) + sizeof (double);
1448 case DBUS_TYPE_STRING:
1452 /* Demarshal the length */
1453 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1455 *end_pos = pos + len + 1;
1459 case DBUS_TYPE_NAMED:
1463 /* Demarshal the string length */
1464 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1466 *end_pos = pos + len + 1;
1468 /* Demarshal the data length */
1469 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1471 *end_pos = pos + len;
1475 case DBUS_TYPE_ARRAY:
1479 /* Demarshal the length */
1480 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1482 *end_pos = pos + len;
1486 case DBUS_TYPE_DICT:
1490 /* Demarshal the length */
1491 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1493 *end_pos = pos + len;
1498 _dbus_warn ("Unknown message arg type %d\n", type);
1499 _dbus_assert_not_reached ("Unknown message argument type\n");
1503 if (*end_pos > _dbus_string_get_length (str))
1510 * Demarshals and validates a length; returns < 0 if the validation
1511 * fails. The length is required to be small enough that
1512 * len*sizeof(double) will not overflow, and small enough to fit in a
1513 * signed integer. DOES NOT check whether the length points
1514 * beyond the end of the string, because it doesn't know the
1515 * size of array elements.
1517 * @param str the string
1518 * @param byte_order the byte order
1519 * @param pos the unaligned string position (snap to next aligned)
1520 * @param new_pos return location for new position.
1523 demarshal_and_validate_len (const DBusString *str,
1528 int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1531 _dbus_assert (new_pos != NULL);
1533 if ((align_4 + 4) > _dbus_string_get_length (str))
1535 _dbus_verbose ("not enough room in message for array length\n");
1539 if (!_dbus_string_validate_nul (str, pos,
1542 _dbus_verbose ("array length alignment padding not initialized to nul\n");
1546 len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
1548 /* note that the len is the number of bytes, so we need it to be
1549 * at least SIZE_T_MAX, but make it smaller just to keep things
1550 * sane. We end up using ints for most sizes to avoid unsigned mess
1551 * so limit to maximum 32-bit signed int divided by at least 8, more
1552 * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
1554 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
1555 if (len > MAX_ARRAY_LENGTH)
1557 _dbus_verbose ("array length %u exceeds maximum of %u\n",
1558 len, MAX_ARRAY_LENGTH);
1566 validate_string (const DBusString *str,
1568 int len_without_nul,
1571 *end_pos = pos + len_without_nul + 1;
1573 if (*end_pos > _dbus_string_get_length (str))
1575 _dbus_verbose ("string length outside length of the message\n");
1579 if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
1581 _dbus_verbose ("string arg not nul-terminated\n");
1585 if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
1587 _dbus_verbose ("string is not valid UTF-8\n");
1595 * Validates and returns a typecode at a specific position
1598 * @param str a string
1599 * @param type the type of the argument
1600 * @param pos the pos where the typecode starts
1601 * @param end_pos pointer where the position right
1602 * after the end position will follow
1603 * @returns #TRUE if the type is valid.
1606 _dbus_marshal_validate_type (const DBusString *str,
1613 if (pos >= _dbus_string_get_length (str))
1616 data = _dbus_string_get_const_data_len (str, pos, 1);
1618 if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1621 if (end_pos != NULL)
1631 * Validates an argument of a specific type, checking that it
1632 * is well-formed, for example no ludicrous length fields, strings
1633 * are nul-terminated, etc.
1634 * Returns the end position of the argument in end_pos, and
1635 * returns #TRUE if a valid arg begins at "pos"
1637 * @todo security: need to audit this function.
1639 * @todo For array types that can't be invalid, we should not
1640 * walk the whole array validating it. e.g. just skip all the
1641 * int values in an int array.
1643 * @param str a string
1644 * @param byte_order the byte order to use
1645 * @param depth current recursion depth, to prevent excessive recursion
1646 * @param type the type of the argument
1647 * @param array_type_pos the position of the current array type, or
1648 * -1 if not in an array
1649 * @param pos the pos where the arg starts
1650 * @param end_pos pointer where the position right
1651 * after the end position will follow
1652 * @returns #TRUE if the arg is valid.
1655 _dbus_marshal_validate_arg (const DBusString *str,
1663 if (pos > _dbus_string_get_length (str))
1665 _dbus_verbose ("Validation went off the end of the message\n");
1669 #define MAX_VALIDATION_DEPTH 32
1671 if (depth > MAX_VALIDATION_DEPTH)
1673 _dbus_verbose ("Maximum recursion depth reached validating message\n");
1679 case DBUS_TYPE_INVALID:
1687 case DBUS_TYPE_BYTE:
1688 if (1 > _dbus_string_get_length (str) - pos)
1690 _dbus_verbose ("no room for byte value\n");
1697 case DBUS_TYPE_BOOLEAN:
1701 if (1 > _dbus_string_get_length (str) - pos)
1703 _dbus_verbose ("no room for boolean value\n");
1707 c = _dbus_string_get_byte (str, pos);
1709 if (c != 0 && c != 1)
1711 _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
1719 case DBUS_TYPE_INT32:
1720 case DBUS_TYPE_UINT32:
1722 int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1724 if (!_dbus_string_validate_nul (str, pos,
1727 _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
1731 *end_pos = align_4 + 4;
1735 case DBUS_TYPE_INT64:
1736 case DBUS_TYPE_UINT64:
1738 int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
1740 if (!_dbus_string_validate_nul (str, pos,
1743 _dbus_verbose ("int64/uint64 alignment padding not initialized to nul\n");
1747 *end_pos = align_8 + 8;
1751 case DBUS_TYPE_DOUBLE:
1753 int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
1755 _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
1757 if (!_dbus_string_validate_nul (str, pos,
1760 _dbus_verbose ("double alignment padding not initialized to nul\n");
1764 *end_pos = align_8 + 8;
1768 case DBUS_TYPE_STRING:
1772 /* Demarshal the length, which does NOT include
1775 len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1779 if (!validate_string (str, pos, len, end_pos))
1784 case DBUS_TYPE_NAMED:
1788 /* Demarshal the string length, which does NOT include
1791 len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1795 if (!validate_string (str, pos, len, &pos))
1799 len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1803 *end_pos = pos + len;
1807 case DBUS_TYPE_ARRAY:
1813 if (array_type_pos == -1)
1815 array_type_pos = pos;
1819 if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
1821 _dbus_verbose ("invalid array type\n");
1825 /* NIL values take up no space, so you couldn't iterate over an array of them.
1826 * array of nil seems useless anyway; the useful thing might be array of
1827 * (nil OR string) but we have no framework for that.
1829 if (array_type == DBUS_TYPE_NIL)
1831 _dbus_verbose ("array of NIL is not allowed\n");
1835 while (array_type == DBUS_TYPE_ARRAY);
1840 if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
1842 _dbus_verbose ("invalid array type\n");
1846 len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1850 if (len > _dbus_string_get_length (str) - pos)
1852 _dbus_verbose ("array length outside length of the message\n");
1860 if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
1861 array_type, array_type_pos, pos, &pos))
1867 /* This should not be able to happen, as long as validate_arg moves forward;
1868 * but the check is here just to be paranoid.
1870 _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
1877 _dbus_verbose ("array contents exceeds array length %d by %d\n", len, pos - end);
1885 case DBUS_TYPE_DICT:
1891 len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1895 if (len > _dbus_string_get_length (str) - pos)
1897 _dbus_verbose ("dict length outside length of the message\n");
1906 if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
1907 DBUS_TYPE_STRING, -1, pos, &pos))
1910 if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
1912 _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
1916 /* Validate element */
1917 if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
1918 dict_type, -1, pos, &pos))
1924 _dbus_verbose ("dict contents exceed stated dict length\n");
1933 _dbus_verbose ("Unknown message arg type %d\n", type);
1937 if (*end_pos > _dbus_string_get_length (str))
1945 * If in verbose mode, print a block of binary data.
1947 * @todo right now it prints even if not in verbose mode
1949 * @param data the data
1950 * @param len the length of the data
1953 _dbus_verbose_bytes (const unsigned char *data,
1957 const unsigned char *aligned;
1959 _dbus_assert (len >= 0);
1961 /* Print blanks on first row if appropriate */
1962 aligned = _DBUS_ALIGN_ADDRESS (data, 4);
1965 _dbus_assert (aligned <= data);
1967 if (aligned != data)
1969 _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned);
1970 while (aligned != data)
1972 _dbus_verbose (" ");
1977 /* now print the bytes */
1981 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1983 _dbus_verbose ("%4d\t%p: ",
1987 if (data[i] >= 32 &&
1989 _dbus_verbose (" '%c' ", data[i]);
1991 _dbus_verbose ("0x%s%x ",
1992 data[i] <= 0xf ? "0" : "", data[i]);
1996 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1999 _dbus_verbose ("BE: %d LE: %d",
2000 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
2001 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
2004 _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
2006 _dbus_verbose (" dbl: %g",
2007 *(double*)&data[i-8]);
2010 _dbus_verbose ("\n");
2014 _dbus_verbose ("\n");
2018 * Dump the given part of the string to verbose log.
2020 * @param str the string
2021 * @param start the start of range to dump
2022 * @param len length of range
2025 _dbus_verbose_bytes_of_string (const DBusString *str,
2032 real_len = _dbus_string_get_length (str);
2034 _dbus_assert (start >= 0);
2036 if (start > real_len)
2038 _dbus_verbose (" [%d,%d) is not inside string of length %d\n",
2039 start, len, real_len);
2043 if ((start + len) > real_len)
2045 _dbus_verbose (" [%d,%d) extends outside string of length %d\n",
2046 start, len, real_len);
2047 len = real_len - start;
2050 d = _dbus_string_get_const_data_len (str, start, len);
2052 _dbus_verbose_bytes (d, len);
2057 #ifdef DBUS_BUILD_TESTS
2058 #include "dbus-test.h"
2062 _dbus_marshal_test (void)
2067 dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
2068 #ifdef DBUS_HAVE_INT64
2069 dbus_int64_t array3[3] = { 0x123ffffffff, 0x456ffffffff, 0x789ffffffff }, *array4;
2072 if (!_dbus_string_init (&str))
2073 _dbus_assert_not_reached ("failed to init string");
2075 /* Marshal doubles */
2076 if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
2077 _dbus_assert_not_reached ("could not marshal double value");
2078 if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
2079 _dbus_assert_not_reached ("demarshal failed");
2081 if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
2082 _dbus_assert_not_reached ("could not marshal double value");
2083 if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
2084 _dbus_assert_not_reached ("demarshal failed");
2086 /* Marshal signed integers */
2087 if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
2088 _dbus_assert_not_reached ("could not marshal signed integer value");
2089 if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
2090 _dbus_assert_not_reached ("demarshal failed");
2092 if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
2093 _dbus_assert_not_reached ("could not marshal signed integer value");
2094 if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
2095 _dbus_assert_not_reached ("demarshal failed");
2097 /* Marshal unsigned integers */
2098 if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
2099 _dbus_assert_not_reached ("could not marshal signed integer value");
2100 if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
2101 _dbus_assert_not_reached ("demarshal failed");
2103 if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
2104 _dbus_assert_not_reached ("could not marshal signed integer value");
2105 if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
2106 _dbus_assert_not_reached ("demarshal failed");
2108 #ifdef DBUS_HAVE_INT64
2109 /* Marshal signed integers */
2110 if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2111 _dbus_assert_not_reached ("could not marshal signed integer value");
2112 if (!_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_INT64_CONSTANT (-0x123456789abc7))
2113 _dbus_assert_not_reached ("demarshal failed");
2115 if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2116 _dbus_assert_not_reached ("could not marshal signed integer value");
2117 if (!_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_INT64_CONSTANT (-0x123456789abc7))
2118 _dbus_assert_not_reached ("demarshal failed");
2120 /* Marshal unsigned integers */
2121 if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2122 _dbus_assert_not_reached ("could not marshal signed integer value");
2123 if (!_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7))
2124 _dbus_assert_not_reached ("demarshal failed");
2126 if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2127 _dbus_assert_not_reached ("could not marshal signed integer value");
2128 if (!_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7))
2129 _dbus_assert_not_reached ("demarshal failed");
2130 #endif /* DBUS_HAVE_INT64 */
2132 /* Marshal strings */
2133 tmp1 = "This is the dbus test string";
2134 if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
2135 _dbus_assert_not_reached ("could not marshal string");
2136 tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
2137 if (!strcmp (tmp1, tmp2) == 0)
2138 _dbus_assert_not_reached ("demarshal failed");
2141 tmp1 = "This is the dbus test string";
2142 if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
2143 _dbus_assert_not_reached ("could not marshal string");
2144 tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
2145 if (!strcmp (tmp1, tmp2) == 0)
2146 _dbus_assert_not_reached ("demarshal failed");
2149 /* Marshal signed integer arrays */
2150 if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
2151 _dbus_assert_not_reached ("could not marshal integer array");
2152 if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len))
2153 _dbus_assert_not_reached ("could not demarshal integer array");
2156 _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2159 #ifdef DBUS_HAVE_INT64
2160 /* Marshal 64-bit signed integer arrays */
2161 if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3))
2162 _dbus_assert_not_reached ("could not marshal integer array");
2163 if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len))
2164 _dbus_assert_not_reached ("could not demarshal integer array");
2167 _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2171 _dbus_string_free (&str);
2177 #endif /* DBUS_BUILD_TESTS */