2003-07-06 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / dbus / dbus-marshal.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-marshal.c  Marshalling routines
3  *
4  * Copyright (C) 2002 CodeFactory AB
5  * Copyright (C) 2003 Red Hat, Inc.
6  *
7  * Licensed under the Academic Free License version 1.2
8  * 
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.
13  *
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.
18  * 
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
22  *
23  */
24
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"
29
30 #include <string.h>
31
32 /**
33  * @defgroup DBusMarshal marshaling and unmarshaling
34  * @ingroup  DBusInternals
35  * @brief functions to marshal/unmarshal data from the wire
36  *
37  * Types and functions related to converting primitive data types from
38  * wire format to native machine format, and vice versa.
39  *
40  * @{
41  */
42
43 static dbus_uint32_t
44 unpack_4_octets (int                  byte_order,
45                  const unsigned char *data)
46 {
47   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
48   
49   if (byte_order == DBUS_LITTLE_ENDIAN)
50     return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
51   else
52     return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
53 }
54
55 #ifndef DBUS_HAVE_INT64
56 /* from ORBit */
57 static void
58 swap_bytes (unsigned char *data,
59             unsigned int   len)
60 {
61   unsigned char *p1 = data;
62   unsigned char *p2 = data + len - 1;
63
64   while (p1 < p2)
65     {
66       unsigned char tmp = *p1;
67       *p1 = *p2;
68       *p2 = tmp;
69
70       --p2;
71       ++p1;
72     }
73 }
74 #endif /* !DBUS_HAVE_INT64 */
75
76 typedef union
77 {
78 #ifdef DBUS_HAVE_INT64
79   dbus_int64_t  s;
80   dbus_uint64_t u;
81 #endif
82   double d;
83 #ifdef WORDS_BIGENDIAN
84   struct
85   {
86     dbus_uint32_t high;
87     dbus_uint32_t low;
88   } bits;
89 #else
90   struct
91   {
92     dbus_uint32_t low;
93     dbus_uint32_t high;
94   } bits;  
95 #endif
96 } DBusOctets8;
97
98 static DBusOctets8
99 unpack_8_octets (int                  byte_order,
100                  const unsigned char *data)
101 {
102   DBusOctets8 r;
103   
104   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
105   _dbus_assert (sizeof (r) == 8);
106   
107 #ifdef DBUS_HAVE_INT64
108   if (byte_order == DBUS_LITTLE_ENDIAN)
109     r.u = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
110   else
111     r.u = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
112 #else
113   r.d = *(double*)data;
114   swap_bytes (&r, sizeof (r));
115 #endif
116   
117   return r;
118 }
119
120 /**
121  * Unpacks a 32 bit unsigned integer from a data pointer
122  *
123  * @param byte_order The byte order to use
124  * @param data the data pointer
125  * @returns the integer
126  */
127 dbus_uint32_t
128 _dbus_unpack_uint32 (int                  byte_order,
129                      const unsigned char *data)
130 {
131   return unpack_4_octets (byte_order, data);
132 }  
133
134 /**
135  * Unpacks a 32 bit signed integer from a data pointer
136  *
137  * @param byte_order The byte order to use
138  * @param data the data pointer
139  * @returns the integer
140  */
141 dbus_int32_t
142 _dbus_unpack_int32 (int                  byte_order,
143                     const unsigned char *data)
144 {
145   return (dbus_int32_t) unpack_4_octets (byte_order, data);
146 }
147
148 #ifdef DBUS_HAVE_INT64
149 /**
150  * Unpacks a 64 bit unsigned integer from a data pointer
151  *
152  * @param byte_order The byte order to use
153  * @param data the data pointer
154  * @returns the integer
155  */
156 dbus_uint64_t
157 _dbus_unpack_uint64 (int                  byte_order,
158                      const unsigned char *data)
159 {
160   DBusOctets8 r;
161   
162   r = unpack_8_octets (byte_order, data);
163
164   return r.u;
165 }  
166
167 /**
168  * Unpacks a 64 bit signed integer from a data pointer
169  *
170  * @param byte_order The byte order to use
171  * @param data the data pointer
172  * @returns the integer
173  */
174 dbus_int64_t
175 _dbus_unpack_int64 (int                  byte_order,
176                     const unsigned char *data)
177 {
178   DBusOctets8 r;
179   
180   r = unpack_8_octets (byte_order, data);
181
182   return r.s;
183 }
184
185 #endif /* DBUS_HAVE_INT64 */
186
187 static void
188 pack_4_octets (dbus_uint32_t   value,
189                int             byte_order,
190                unsigned char  *data)
191 {
192   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
193   
194   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
195     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);       
196   else
197     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
198 }
199
200 static void
201 pack_8_octets (DBusOctets8     value,
202                int             byte_order,
203                unsigned char  *data)
204 {
205   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
206
207 #ifdef DBUS_HAVE_INT64
208   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
209     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u); 
210   else
211     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u);
212 #else
213   memcpy (data, &value, 8);
214   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
215     swap_bytes ((unsigned char *)data, 8);
216 #endif
217 }
218
219 /**
220  * Packs a 32 bit unsigned integer into a data pointer.
221  *
222  * @param value the value
223  * @param byte_order the byte order to use
224  * @param data the data pointer
225  */
226 void
227 _dbus_pack_uint32 (dbus_uint32_t   value,
228                    int             byte_order,
229                    unsigned char  *data)
230 {
231   pack_4_octets (value, byte_order, data);
232 }
233
234 /**
235  * Packs a 32 bit signed integer into a data pointer.
236  *
237  * @param value the value
238  * @param byte_order the byte order to use
239  * @param data the data pointer
240  */
241 void
242 _dbus_pack_int32 (dbus_int32_t   value,
243                   int            byte_order,
244                   unsigned char *data)
245 {
246   pack_4_octets ((dbus_uint32_t) value, byte_order, data);
247 }
248
249 #ifdef DBUS_HAVE_INT64
250 /**
251  * Packs a 64 bit unsigned integer into a data pointer.
252  *
253  * @param value the value
254  * @param byte_order the byte order to use
255  * @param data the data pointer
256  */
257 void
258 _dbus_pack_uint64 (dbus_uint64_t   value,
259                    int             byte_order,
260                    unsigned char  *data)
261 {
262   DBusOctets8 r;
263   r.u = value;
264   pack_8_octets (r, byte_order, data);
265 }
266
267 /**
268  * Packs a 64 bit signed integer into a data pointer.
269  *
270  * @param value the value
271  * @param byte_order the byte order to use
272  * @param data the data pointer
273  */
274 void
275 _dbus_pack_int64 (dbus_int64_t   value,
276                   int            byte_order,
277                   unsigned char *data)
278 {
279   DBusOctets8 r;
280   r.s = value;
281   pack_8_octets (r, byte_order, data);
282 }
283 #endif /* DBUS_HAVE_INT64 */
284
285 static void
286 set_4_octets (DBusString          *str,
287               int                  byte_order,
288               int                  offset,
289               dbus_uint32_t        value)
290 {
291   char *data;
292   
293   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
294                 byte_order == DBUS_BIG_ENDIAN);
295   
296   data = _dbus_string_get_data_len (str, offset, 4);
297
298   _dbus_pack_uint32 (value, byte_order, data);
299 }
300
301 static void
302 set_8_octets (DBusString          *str,
303               int                  byte_order,
304               int                  offset,
305               DBusOctets8          value)
306 {
307   char *data;
308   
309   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
310                 byte_order == DBUS_BIG_ENDIAN);
311   
312   data = _dbus_string_get_data_len (str, offset, 8);
313
314   pack_8_octets (value, byte_order, data);
315 }
316
317 /**
318  * Sets the 4 bytes at the given offset to a marshaled signed integer,
319  * replacing anything found there previously.
320  *
321  * @param str the string to write the marshalled int to
322  * @param offset the byte offset where int should be written
323  * @param byte_order the byte order to use
324  * @param value the value
325  * 
326  */
327 void
328 _dbus_marshal_set_int32 (DBusString          *str,
329                          int                  byte_order,
330                          int                  offset,
331                          dbus_int32_t         value)
332 {
333   set_4_octets (str, byte_order, offset, (dbus_uint32_t) value);
334 }
335
336 /**
337  * Sets the 4 bytes at the given offset to a marshaled unsigned
338  * integer, replacing anything found there previously.
339  *
340  * @param str the string to write the marshalled int to
341  * @param offset the byte offset where int should be written
342  * @param byte_order the byte order to use
343  * @param value the value
344  * 
345  */
346 void
347 _dbus_marshal_set_uint32 (DBusString          *str,
348                           int                  byte_order,
349                           int                  offset,
350                           dbus_uint32_t        value)
351 {
352   set_4_octets (str, byte_order, offset, value);
353 }
354
355 #ifdef DBUS_HAVE_INT64
356
357 /**
358  * Sets the 8 bytes at the given offset to a marshaled signed integer,
359  * replacing anything found there previously.
360  *
361  * @param str the string to write the marshalled int to
362  * @param offset the byte offset where int should be written
363  * @param byte_order the byte order to use
364  * @param value the value
365  * 
366  */
367 void
368 _dbus_marshal_set_int64 (DBusString          *str,
369                          int                  byte_order,
370                          int                  offset,
371                          dbus_int64_t         value)
372 {
373   DBusOctets8 r;
374   r.s = value;
375   set_8_octets (str, byte_order, offset, r);
376 }
377
378 /**
379  * Sets the 8 bytes at the given offset to a marshaled unsigned
380  * integer, replacing anything found there previously.
381  *
382  * @param str the string to write the marshalled int to
383  * @param offset the byte offset where int should be written
384  * @param byte_order the byte order to use
385  * @param value the value
386  * 
387  */
388 void
389 _dbus_marshal_set_uint64 (DBusString          *str,
390                           int                  byte_order,
391                           int                  offset,
392                           dbus_uint64_t        value)
393 {
394   DBusOctets8 r;
395   r.u = value;
396   set_8_octets (str, byte_order, offset, r);
397 }
398 #endif /* DBUS_HAVE_INT64 */
399
400 /**
401  * Sets the existing marshaled string at the given offset with
402  * a new marshaled string. The given offset must point to
403  * an existing string or the wrong length will be deleted
404  * and replaced with the new string.
405  *
406  * @param str the string to write the marshalled string to
407  * @param offset the byte offset where string should be written
408  * @param byte_order the byte order to use
409  * @param value the value
410  * @param len the length to use
411  * @returns #TRUE on success
412  * 
413  */
414 dbus_bool_t
415 _dbus_marshal_set_string (DBusString          *str,
416                           int                  byte_order,
417                           int                  offset,
418                           const DBusString    *value,
419                           int                  len)
420 {
421   int old_len;
422   
423   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
424                 byte_order == DBUS_BIG_ENDIAN);
425   
426   old_len = _dbus_demarshal_uint32 (str, byte_order,
427                                     offset, NULL);
428
429   if (!_dbus_string_replace_len (value, 0, len,
430                                  str, offset + 4, old_len))
431     return FALSE;
432
433   _dbus_marshal_set_uint32 (str, byte_order,
434                             offset, len);
435
436   return TRUE;
437 }
438
439 /**
440  * Sets the existing marshaled object ID at the given offset to a new
441  * value. The given offset must point to an existing object ID or this
442  * function doesn't make sense.
443  *
444  * @param str the string to write the marshalled string to
445  * @param offset the byte offset where string should be written
446  * @param byte_order the byte order to use
447  * @param value the new value
448  */
449 void
450 _dbus_marshal_set_object_id (DBusString         *str,
451                              int                 byte_order,
452                              int                 offset,
453                              const DBusObjectID *value)
454 {
455   DBusOctets8 r;
456 #ifdef DBUS_HAVE_INT64
457   r.u = dbus_object_id_get_as_integer (value);
458 #else
459   r.bits.low = dbus_object_id_get_low_bits (value);
460   r.bits.high = dbus_object_id_get_high_bits (value);
461 #endif
462   _dbus_assert (r.bits.low == dbus_object_id_get_low_bits (value));
463   _dbus_assert (r.bits.high == dbus_object_id_get_high_bits (value));
464   
465   set_8_octets (str, byte_order, offset, r);
466 }
467
468 static dbus_bool_t
469 marshal_4_octets (DBusString   *str,
470                   int           byte_order,
471                   dbus_uint32_t value)
472 {
473   _dbus_assert (sizeof (value) == 4);
474   
475   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
476     value = DBUS_UINT32_SWAP_LE_BE (value);
477
478   return _dbus_string_append_4_aligned (str,
479                                         (const unsigned char *)&value);
480 }
481
482 static dbus_bool_t
483 marshal_8_octets (DBusString *str,
484                   int         byte_order,
485                   DBusOctets8 value)
486 {
487   _dbus_assert (sizeof (value) == 8);
488   
489   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
490     pack_8_octets (value, byte_order, (unsigned char*) &value); /* pack into self, swapping as we go */
491
492   return _dbus_string_append_8_aligned (str,
493                                         (const unsigned char *)&value);
494 }
495
496 /**
497  * Marshals a double value.
498  *
499  * @param str the string to append the marshalled value to
500  * @param byte_order the byte order to use
501  * @param value the value
502  * @returns #TRUE on success
503  */
504 dbus_bool_t
505 _dbus_marshal_double (DBusString *str,
506                       int         byte_order,
507                       double      value)
508 {
509   DBusOctets8 r;
510   r.d = value;
511   return marshal_8_octets (str, byte_order, r);
512 }
513
514 /**
515  * Marshals a 32 bit signed integer value.
516  *
517  * @param str the string to append the marshalled value to
518  * @param byte_order the byte order to use
519  * @param value the value
520  * @returns #TRUE on success
521  */
522 dbus_bool_t
523 _dbus_marshal_int32  (DBusString   *str,
524                       int           byte_order,
525                       dbus_int32_t  value)
526 {
527   return marshal_4_octets (str, byte_order, (dbus_uint32_t) value);
528 }
529
530 /**
531  * Marshals a 32 bit unsigned integer value.
532  *
533  * @param str the string to append the marshalled value to
534  * @param byte_order the byte order to use
535  * @param value the value
536  * @returns #TRUE on success
537  */
538 dbus_bool_t
539 _dbus_marshal_uint32 (DBusString    *str,
540                       int            byte_order,
541                       dbus_uint32_t  value)
542 {
543   return marshal_4_octets (str, byte_order, value);
544 }
545
546
547 #ifdef DBUS_HAVE_INT64
548 /**
549  * Marshals a 64 bit signed integer value.
550  *
551  * @param str the string to append the marshalled value to
552  * @param byte_order the byte order to use
553  * @param value the value
554  * @returns #TRUE on success
555  */
556 dbus_bool_t
557 _dbus_marshal_int64  (DBusString   *str,
558                       int           byte_order,
559                       dbus_int64_t  value)
560 {
561   DBusOctets8 r;
562   r.s = value;
563   return marshal_8_octets (str, byte_order, r);
564 }
565
566 /**
567  * Marshals a 64 bit unsigned integer value.
568  *
569  * @param str the string to append the marshalled value to
570  * @param byte_order the byte order to use
571  * @param value the value
572  * @returns #TRUE on success
573  */
574 dbus_bool_t
575 _dbus_marshal_uint64 (DBusString    *str,
576                       int            byte_order,
577                       dbus_uint64_t  value)
578 {
579   DBusOctets8 r;
580   r.u = value;
581   return marshal_8_octets (str, byte_order, r);
582 }
583
584 #endif /* DBUS_HAVE_INT64 */
585
586 /**
587  * Marshals a UTF-8 string
588  *
589  * @todo: If the string append fails we need to restore
590  * the old length. (also for other marshallers)
591  * 
592  * @param str the string to append the marshalled value to
593  * @param byte_order the byte order to use
594  * @param value the string
595  * @returns #TRUE on success
596  */
597 dbus_bool_t
598 _dbus_marshal_string (DBusString    *str,
599                       int            byte_order,
600                       const char    *value)
601 {
602   int len, old_string_len;
603
604   old_string_len = _dbus_string_get_length (str);
605   
606   len = strlen (value);
607
608   if (!_dbus_marshal_uint32 (str, byte_order, len))
609     {
610       /* Restore the previous length */
611       _dbus_string_set_length (str, old_string_len);
612
613       return FALSE;
614     }
615
616   return _dbus_string_append_len (str, value, len + 1);
617 }
618
619 /**
620  * Marshals a byte array
621  *
622  * @param str the string to append the marshalled value to
623  * @param byte_order the byte order to use
624  * @param value the array
625  * @param len number of elements in the array
626  * @returns #TRUE on success
627  */
628 dbus_bool_t
629 _dbus_marshal_byte_array (DBusString          *str,
630                           int                  byte_order,
631                           const unsigned char *value,
632                           int                  len)
633 {
634   int old_string_len;
635
636   old_string_len = _dbus_string_get_length (str);
637   
638   if (!_dbus_marshal_uint32 (str, byte_order, len))
639     {
640       /* Restore the previous length */
641       _dbus_string_set_length (str, old_string_len);
642
643       return FALSE;
644     }
645
646   if (len == 0)
647     return TRUE;
648   else
649     return _dbus_string_append_len (str, value, len);
650 }
651
652 static dbus_bool_t
653 marshal_4_octets_array (DBusString          *str,
654                         int                  byte_order,
655                         const dbus_uint32_t *value,
656                         int                  len)
657 {
658   int old_string_len;
659   int array_start;
660
661   old_string_len = _dbus_string_get_length (str);
662
663   if (!_dbus_marshal_uint32 (str, byte_order, len * 4))
664     goto error;
665
666   array_start = _dbus_string_get_length (str);
667   
668   if (!_dbus_string_append_len (str, (const unsigned char*) value,
669                                 len * 4))
670     goto error;
671   
672   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
673     {
674       const unsigned char *d;
675       const unsigned char *end;
676       
677       d = _dbus_string_get_data (str) + array_start;
678       end = d + len * 4;
679       while (d != end)
680         {
681           *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
682           d += 4;
683         }
684     }
685
686   return TRUE;
687   
688  error:
689   /* Restore previous length */
690   _dbus_string_set_length (str, old_string_len);
691   
692   return FALSE;  
693 }
694
695 static dbus_bool_t
696 marshal_8_octets_array (DBusString          *str,
697                         int                  byte_order,
698                         const DBusOctets8   *value,
699                         int                  len)
700 {
701   int old_string_len;
702   int array_start;
703
704   old_string_len = _dbus_string_get_length (str);
705
706   if (!_dbus_marshal_uint32 (str, byte_order, len * 8))
707     goto error;
708
709   array_start = _dbus_string_get_length (str);
710   
711   if (!_dbus_string_append_len (str, (const unsigned char*) value,
712                                 len * 8))
713     goto error;
714   
715   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
716     {
717       const unsigned char *d;
718       const unsigned char *end;
719       
720       d = _dbus_string_get_data (str) + array_start;
721       end = d + len * 8;
722       while (d != end)
723         {
724 #ifdef DBUS_HAVE_INT64
725           *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
726 #else
727           swap_bytes (d, 8);
728 #endif
729           d += 8;
730         }
731     }
732
733   return TRUE;
734   
735  error:
736   /* Restore previous length */
737   _dbus_string_set_length (str, old_string_len);
738   
739   return FALSE;  
740 }
741
742 /**
743  * Marshals a 32 bit signed integer array
744  *
745  * @param str the string to append the marshalled value to
746  * @param byte_order the byte order to use
747  * @param value the array
748  * @param len the length of the array
749  * @returns #TRUE on success
750  */
751 dbus_bool_t
752 _dbus_marshal_int32_array (DBusString         *str,
753                            int                 byte_order,
754                            const dbus_int32_t *value,
755                            int                 len)
756 {
757   return marshal_4_octets_array (str, byte_order,
758                                  (const dbus_uint32_t*) value,
759                                  len);
760 }
761
762 /**
763  * Marshals a 32 bit unsigned integer array
764  *
765  * @param str the string to append the marshalled value to
766  * @param byte_order the byte order to use
767  * @param value the array
768  * @param len the length of the array
769  * @returns #TRUE on success
770  */
771 dbus_bool_t
772 _dbus_marshal_uint32_array (DBusString          *str,
773                             int                  byte_order,
774                             const dbus_uint32_t  *value,
775                             int                  len)
776 {
777   return marshal_4_octets_array (str, byte_order,
778                                  value,
779                                  len);
780 }
781
782 #ifdef DBUS_HAVE_INT64
783
784 /**
785  * Marshals a 64 bit signed integer array
786  *
787  * @param str the string to append the marshalled value to
788  * @param byte_order the byte order to use
789  * @param value the array
790  * @param len the length of the array
791  * @returns #TRUE on success
792  */
793 dbus_bool_t
794 _dbus_marshal_int64_array (DBusString         *str,
795                            int                 byte_order,
796                            const dbus_int64_t *value,
797                            int                 len)
798 {
799   return marshal_8_octets_array (str, byte_order,
800                                  (const DBusOctets8*) value,
801                                  len);
802 }
803
804 /**
805  * Marshals a 64 bit unsigned integer array
806  *
807  * @param str the string to append the marshalled value to
808  * @param byte_order the byte order to use
809  * @param value the array
810  * @param len the length of the array
811  * @returns #TRUE on success
812  */
813 dbus_bool_t
814 _dbus_marshal_uint64_array (DBusString          *str,
815                             int                  byte_order,
816                             const dbus_uint64_t  *value,
817                             int                  len)
818 {
819   return marshal_8_octets_array (str, byte_order,
820                                  (const DBusOctets8*) value,
821                                  len);
822 }
823
824 #endif /* DBUS_HAVE_INT64 */
825
826 /**
827  * Marshals a double array
828  *
829  * @param str the string to append the marshalled value to
830  * @param byte_order the byte order to use
831  * @param value the array
832  * @param len the length of the array
833  * @returns #TRUE on success
834  */
835 dbus_bool_t
836 _dbus_marshal_double_array (DBusString          *str,
837                             int                  byte_order,
838                             const double        *value,
839                             int                  len)
840 {
841   return marshal_8_octets_array (str, byte_order,
842                                  (const DBusOctets8*) value,
843                                  len);
844 }
845
846 /**
847  * Marshals a string array
848  *
849  * @param str the string to append the marshalled value to
850  * @param byte_order the byte order to use
851  * @param value the array
852  * @param len the length of the array
853  * @returns #TRUE on success
854  */
855 dbus_bool_t
856 _dbus_marshal_string_array (DBusString  *str,
857                             int          byte_order,
858                             const char **value,
859                             int          len)
860 {
861   int i, old_string_len, array_start;
862
863   old_string_len = _dbus_string_get_length (str);
864
865   /* Set the length to 0 temporarily */
866   if (!_dbus_marshal_uint32 (str, byte_order, 0))
867     goto error;
868
869   array_start = _dbus_string_get_length (str);
870   
871   for (i = 0; i < len; i++)
872     if (!_dbus_marshal_string (str, byte_order, value[i]))
873       goto error;
874
875   /* Write the length now that we know it */
876   _dbus_marshal_set_uint32 (str, byte_order,
877                             _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
878                             _dbus_string_get_length (str) - array_start);
879   
880   return TRUE;
881   
882  error:
883   /* Restore previous length */
884   _dbus_string_set_length (str, old_string_len);
885   
886   return FALSE;      
887 }
888
889 /**
890  * Marshals an object ID value.
891  *
892  * @param str the string to append the marshalled value to
893  * @param byte_order the byte order to use
894  * @param value the value
895  * @returns #TRUE on success
896  */
897 dbus_bool_t
898 _dbus_marshal_object_id (DBusString            *str,
899                          int                    byte_order,
900                          const DBusObjectID    *value)
901 {
902   DBusOctets8 r;
903 #ifdef DBUS_HAVE_INT64
904   r.u = dbus_object_id_get_as_integer (value);
905 #else
906   r.bits.low = dbus_object_id_get_low_bits (value);
907   r.bits.high = dbus_object_id_get_high_bits (value);
908 #endif
909   _dbus_assert (r.bits.low == dbus_object_id_get_low_bits (value));
910   _dbus_assert (r.bits.high == dbus_object_id_get_high_bits (value));
911   
912   return marshal_8_octets (str, byte_order, r);
913 }
914
915 static dbus_uint32_t
916 demarshal_4_octets (const DBusString *str,
917                     int               byte_order,
918                     int               pos,
919                     int              *new_pos)
920 {
921   const DBusRealString *real = (const DBusRealString*) str;
922   
923   pos = _DBUS_ALIGN_VALUE (pos, 4);
924   
925   if (new_pos)
926     *new_pos = pos + 4;
927
928   return unpack_4_octets (byte_order, real->str + pos);
929 }
930
931 static DBusOctets8
932 demarshal_8_octets (const DBusString *str,
933                     int               byte_order,
934                     int               pos,
935                     int              *new_pos)
936 {
937   const DBusRealString *real = (const DBusRealString*) str;
938   
939   pos = _DBUS_ALIGN_VALUE (pos, 8);
940   
941   if (new_pos)
942     *new_pos = pos + 8;
943
944   return unpack_8_octets (byte_order, real->str + pos);
945 }
946
947 /**
948  * Demarshals a double.
949  *
950  * @param str the string containing the data
951  * @param byte_order the byte order
952  * @param pos the position in the string
953  * @param new_pos the new position of the string
954  * @returns the demarshaled double.
955  */
956 double
957 _dbus_demarshal_double (const DBusString  *str,
958                         int                byte_order,
959                         int                pos,
960                         int               *new_pos)
961 {
962   DBusOctets8 r;
963
964   r = demarshal_8_octets (str, byte_order, pos, new_pos);
965
966   return r.d;
967 }
968
969 /**
970  * Demarshals a 32 bit signed integer.
971  *
972  * @param str the string containing the data
973  * @param byte_order the byte order
974  * @param pos the position in the string
975  * @param new_pos the new position of the string
976  * @returns the demarshaled integer.
977  */
978 dbus_int32_t
979 _dbus_demarshal_int32  (const DBusString *str,
980                         int               byte_order,
981                         int               pos,
982                         int              *new_pos)
983 {
984   return (dbus_int32_t) demarshal_4_octets (str, byte_order, pos, new_pos);
985 }
986
987 /**
988  * Demarshals a 32 bit unsigned integer.
989  *
990  * @param str the string containing the data
991  * @param byte_order the byte order
992  * @param pos the position in the string
993  * @param new_pos the new position of the string
994  * @returns the demarshaled integer.
995  */
996 dbus_uint32_t
997 _dbus_demarshal_uint32  (const DBusString *str,
998                          int         byte_order,
999                          int         pos,
1000                          int        *new_pos)
1001 {
1002   return demarshal_4_octets (str, byte_order, pos, new_pos);
1003 }
1004
1005 #ifdef DBUS_HAVE_INT64
1006
1007 /**
1008  * Demarshals a 64 bit signed integer.
1009  *
1010  * @param str the string containing the data
1011  * @param byte_order the byte order
1012  * @param pos the position in the string
1013  * @param new_pos the new position of the string
1014  * @returns the demarshaled integer.
1015  */
1016 dbus_int64_t
1017 _dbus_demarshal_int64  (const DBusString *str,
1018                         int               byte_order,
1019                         int               pos,
1020                         int              *new_pos)
1021 {
1022   DBusOctets8 r;
1023
1024   r = demarshal_8_octets (str, byte_order, pos, new_pos);
1025
1026   return r.s;
1027 }
1028
1029 /**
1030  * Demarshals a 64 bit unsigned integer.
1031  *
1032  * @param str the string containing the data
1033  * @param byte_order the byte order
1034  * @param pos the position in the string
1035  * @param new_pos the new position of the string
1036  * @returns the demarshaled integer.
1037  */
1038 dbus_uint64_t
1039 _dbus_demarshal_uint64  (const DBusString *str,
1040                          int         byte_order,
1041                          int         pos,
1042                          int        *new_pos)
1043 {
1044   DBusOctets8 r;
1045
1046   r = demarshal_8_octets (str, byte_order, pos, new_pos);
1047
1048   return r.u;
1049 }
1050
1051 #endif /* DBUS_HAVE_INT64 */
1052
1053 /**
1054  * Demarshals an UTF-8 string.
1055  *
1056  * @todo Should we check the string to make sure
1057  * that it's  valid UTF-8, and maybe "fix" the string
1058  * if it's broken?
1059  *
1060  * @todo Should probably demarshal to a DBusString,
1061  * having memcpy() in here is Evil(tm).
1062  *
1063  * @param str the string containing the data
1064  * @param byte_order the byte order
1065  * @param pos the position in the string
1066  * @param new_pos the new position of the string
1067  * @returns the demarshaled string.
1068  */
1069 char *
1070 _dbus_demarshal_string (const DBusString *str,
1071                         int               byte_order,
1072                         int               pos,
1073                         int              *new_pos)
1074 {
1075   int len;
1076   char *retval;
1077   const char *data;
1078   
1079   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1080
1081   retval = dbus_malloc (len + 1);
1082
1083   if (!retval)
1084     return NULL;
1085
1086   data = _dbus_string_get_const_data_len (str, pos, len + 1);
1087
1088   if (!data)
1089     return NULL;
1090
1091   memcpy (retval, data, len + 1);
1092
1093   if (new_pos)
1094     *new_pos = pos + len + 1;
1095   
1096   return retval;
1097 }
1098
1099 /**
1100  * Demarshals a byte array.
1101  *
1102  * @todo Should probably demarshal to a DBusString,
1103  * having memcpy() in here is Evil(tm).
1104  *
1105  * @param str the string containing the data
1106  * @param byte_order the byte order
1107  * @param pos the position in the string
1108  * @param new_pos the new position of the string
1109  * @param array the array
1110  * @param array_len length of the demarshaled data
1111  
1112  * @returns #TRUE on success
1113  */
1114 dbus_bool_t
1115 _dbus_demarshal_byte_array (const DBusString  *str,
1116                             int                byte_order,
1117                             int                pos,
1118                             int               *new_pos,
1119                             unsigned char    **array,
1120                             int               *array_len)
1121 {
1122   int len;
1123   unsigned char *retval;
1124   const char *data;
1125
1126   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1127
1128   if (len == 0)
1129     {
1130       *array_len = len;
1131       *array = NULL;
1132
1133       if (new_pos)
1134         *new_pos = pos;
1135       
1136       return TRUE;
1137     }
1138   
1139   retval = dbus_malloc (len);
1140
1141   if (!retval)
1142     return FALSE;
1143
1144   data = _dbus_string_get_const_data_len (str, pos, len);
1145
1146   if (!data)
1147     {
1148       dbus_free (retval);
1149       return FALSE;
1150     }
1151
1152   memcpy (retval, data, len);
1153
1154   if (new_pos)
1155     *new_pos = pos + len;
1156
1157   *array = retval;
1158   *array_len = len;
1159   
1160   return TRUE;
1161 }
1162
1163 static dbus_bool_t
1164 demarshal_4_octets_array (const DBusString  *str,
1165                           int                byte_order,
1166                           int                pos,
1167                           int               *new_pos,
1168                           dbus_uint32_t    **array,
1169                           int               *array_len)
1170 {
1171   int len, i;
1172   dbus_uint32_t *retval;
1173   int byte_len;
1174   
1175   byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1176   len = byte_len / 4;
1177
1178   if (len == 0)
1179     {
1180       *array_len = 0;
1181       *array = NULL;
1182
1183       if (new_pos)
1184         *new_pos = pos;
1185       
1186       return TRUE;
1187     }
1188
1189   if (!_dbus_string_copy_data_len (str, (char**) &retval,
1190                                    pos, byte_len))
1191     return FALSE;
1192   
1193   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1194     {
1195       for (i = 0; i < len; i++)
1196         retval[i] = DBUS_UINT32_SWAP_LE_BE (retval[i]);
1197     }
1198
1199   if (new_pos)
1200     *new_pos = pos + byte_len;
1201
1202   *array_len = len;
1203   *array = retval;
1204   
1205   return TRUE;  
1206 }
1207
1208 static dbus_bool_t
1209 demarshal_8_octets_array (const DBusString  *str,
1210                           int                byte_order,
1211                           int                pos,
1212                           int               *new_pos,
1213                           DBusOctets8      **array,
1214                           int               *array_len)
1215 {
1216   int len, i;
1217   DBusOctets8 *retval;
1218   int byte_len;
1219   
1220   byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1221   len = byte_len / 8;
1222
1223   if (len == 0)
1224     {
1225       *array_len = 0;
1226       *array = NULL;
1227
1228       if (new_pos)
1229         *new_pos = pos;
1230       
1231       return TRUE;
1232     }
1233
1234   if (!_dbus_string_copy_data_len (str, (char**) &retval,
1235                                    pos, byte_len))
1236     return FALSE;
1237   
1238   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1239     {
1240       for (i = 0; i < len; i++)
1241         {
1242 #ifdef DBUS_HAVE_INT64
1243           retval[i].u = DBUS_UINT64_SWAP_LE_BE (retval[i].u);
1244 #else
1245           swap_bytes (&retval[i], 8);
1246 #endif
1247         }
1248     }
1249
1250   if (new_pos)
1251     *new_pos = pos + byte_len;
1252
1253   *array_len = len;
1254   *array = retval;
1255   
1256   return TRUE;  
1257 }
1258
1259 /**
1260  * Demarshals a 32 bit signed integer array.
1261  *
1262  * @param str the string containing the data
1263  * @param byte_order the byte order
1264  * @param pos the position in the string
1265  * @param new_pos the new position of the string
1266  * @param array the array
1267  * @param array_len length of the demarshaled data
1268  * @returns #TRUE on success
1269  */
1270 dbus_bool_t
1271 _dbus_demarshal_int32_array (const DBusString  *str,
1272                              int                byte_order,
1273                              int                pos,
1274                              int               *new_pos,
1275                              dbus_int32_t     **array,
1276                              int               *array_len)
1277 {
1278   return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1279                                    (dbus_uint32_t**) array, array_len);
1280 }
1281
1282 /**
1283  * Demarshals a 32 bit unsigned integer array.
1284  *
1285  * @param str the string containing the data
1286  * @param byte_order the byte order
1287  * @param pos the position in the string
1288  * @param new_pos the new position of the string
1289  * @param array the array
1290  * @param array_len length of the demarshaled data
1291  * @returns #TRUE on success
1292  */
1293 dbus_bool_t
1294 _dbus_demarshal_uint32_array (const DBusString  *str,
1295                               int                byte_order,
1296                               int                pos,
1297                               int               *new_pos,
1298                               dbus_uint32_t    **array,
1299                               int               *array_len)
1300 {
1301   return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1302                                    array, array_len);
1303 }
1304
1305 #ifdef DBUS_HAVE_INT64
1306
1307 /**
1308  * Demarshals a 64 bit signed integer array.
1309  *
1310  * @param str the string containing the data
1311  * @param byte_order the byte order
1312  * @param pos the position in the string
1313  * @param new_pos the new position of the string
1314  * @param array the array
1315  * @param array_len length of the demarshaled data
1316  * @returns #TRUE on success
1317  */
1318 dbus_bool_t
1319 _dbus_demarshal_int64_array (const DBusString  *str,
1320                              int                byte_order,
1321                              int                pos,
1322                              int               *new_pos,
1323                              dbus_int64_t     **array,
1324                              int               *array_len)
1325 {
1326   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1327                                    (DBusOctets8**) array, array_len);
1328 }
1329
1330 /**
1331  * Demarshals a 64 bit unsigned integer array.
1332  *
1333  * @param str the string containing the data
1334  * @param byte_order the byte order
1335  * @param pos the position in the string
1336  * @param new_pos the new position of the string
1337  * @param array the array
1338  * @param array_len length of the demarshaled data
1339  * @returns #TRUE on success
1340  */
1341 dbus_bool_t
1342 _dbus_demarshal_uint64_array (const DBusString  *str,
1343                               int                byte_order,
1344                               int                pos,
1345                               int               *new_pos,
1346                               dbus_uint64_t    **array,
1347                               int               *array_len)
1348 {
1349   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1350                                    (DBusOctets8**) array, array_len);
1351 }
1352
1353 #endif /* DBUS_HAVE_INT64 */
1354
1355 /**
1356  * Demarshals a double array.
1357  *
1358  * @param str the string containing the data
1359  * @param byte_order the byte order
1360  * @param pos the position in the string
1361  * @param new_pos the new position of the string
1362  * @param array the array
1363  * @param array_len length of the demarshaled data
1364  * @returns #TRUE on success
1365  */
1366 dbus_bool_t
1367 _dbus_demarshal_double_array (const DBusString  *str,
1368                               int                byte_order,
1369                               int                pos,
1370                               int               *new_pos,
1371                               double           **array,
1372                               int               *array_len)
1373 {
1374   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1375                                    (DBusOctets8**) array, array_len);
1376 }
1377
1378 /**
1379  * Demarshals a string array.
1380  *
1381  * @param str the string containing the data
1382  * @param byte_order the byte order
1383  * @param pos the position in the string
1384  * @param new_pos the new position of the string
1385  * @param array the array
1386  * @param array_len length of the demarshaled data
1387  * @returns #TRUE on success
1388  */
1389 dbus_bool_t
1390 _dbus_demarshal_string_array (const DBusString   *str,
1391                               int                 byte_order,
1392                               int                 pos,
1393                               int                *new_pos,
1394                               char             ***array,
1395                               int                *array_len)
1396 {
1397   int bytes_len, i;
1398   int len, allocated;
1399   int end_pos;
1400   char **retval;
1401   
1402   bytes_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1403   
1404   if (bytes_len == 0)
1405     {
1406       *array_len = 0;
1407       *array = NULL;
1408
1409       if (new_pos)
1410         *new_pos = pos;
1411       
1412       return TRUE;
1413     }
1414
1415   len = 0;
1416   allocated = 4;
1417   end_pos = pos + bytes_len;
1418   
1419   retval = dbus_new (char *, allocated);
1420
1421   if (!retval)
1422     return FALSE;
1423
1424   while (pos < end_pos)
1425     {
1426       retval[len] = _dbus_demarshal_string (str, byte_order, pos, &pos);
1427       
1428       if (retval[len] == NULL)
1429         goto error;
1430       
1431       len += 1;
1432
1433       if (len >= allocated - 1) /* -1 for NULL termination */
1434         {
1435           char **newp;
1436           newp = dbus_realloc (retval,
1437                                sizeof (char*) * allocated * 2);
1438           if (newp == NULL)
1439             goto error;
1440
1441           allocated *= 2;
1442           retval = newp;
1443         }
1444     }
1445       
1446   retval[len] = NULL;
1447
1448   if (new_pos)
1449     *new_pos = pos;
1450   
1451   *array = retval;
1452   *array_len = len;
1453   
1454   return TRUE;
1455
1456  error:
1457   for (i = 0; i < len; i++)
1458     dbus_free (retval[i]);
1459   dbus_free (retval);
1460
1461   return FALSE;
1462 }
1463
1464 /**
1465  * Demarshals an object ID.
1466  *
1467  * @param str the string containing the data
1468  * @param byte_order the byte order
1469  * @param pos the position in the string
1470  * @param new_pos the new position of the string
1471  * @param value address to store new object ID
1472  */
1473 void
1474 _dbus_demarshal_object_id (const DBusString *str,
1475                            int               byte_order,
1476                            int               pos,
1477                            int              *new_pos,
1478                            DBusObjectID     *value)
1479 {
1480   DBusOctets8 r;
1481
1482   r = demarshal_8_octets (str, byte_order, pos, new_pos);
1483
1484 #ifdef DBUS_HAVE_INT64
1485   dbus_object_id_set_as_integer (value, r.u);
1486 #else
1487   dbus_object_id_set_low_bits (value, r.bits.low);
1488   dbus_object_id_set_high_bits (value, r.bits.high);
1489 #endif
1490   _dbus_assert (dbus_object_id_get_low_bits (value) == r.bits.low);
1491   _dbus_assert (dbus_object_id_get_high_bits (value) == r.bits.high);
1492 }
1493
1494 /** 
1495  * Returns the position right after the end of an argument.  PERFORMS
1496  * NO VALIDATION WHATSOEVER. The message must have been previously
1497  * validated.
1498  *
1499  * @param str a string
1500  * @param byte_order the byte order to use
1501  * @param type the type of the argument
1502  * @param pos the pos where the arg starts
1503  * @param end_pos pointer where the position right
1504  * after the end position will follow
1505  * @returns TRUE if more data exists after the arg
1506  */
1507 dbus_bool_t
1508 _dbus_marshal_get_arg_end_pos (const DBusString *str,
1509                                int               byte_order,
1510                                int               type,
1511                                int               pos,
1512                                int              *end_pos)
1513 {
1514   if (pos >= _dbus_string_get_length (str))
1515     return FALSE;
1516
1517   switch (type)
1518     {
1519     case DBUS_TYPE_INVALID:
1520       return FALSE;
1521       break;
1522
1523     case DBUS_TYPE_NIL:
1524       *end_pos = pos;
1525       break;
1526
1527     case DBUS_TYPE_BYTE:
1528       *end_pos = pos + 1;
1529       break;
1530       
1531     case DBUS_TYPE_BOOLEAN:
1532       *end_pos = pos + 1;
1533       break;
1534
1535     case DBUS_TYPE_INT32:
1536     case DBUS_TYPE_UINT32:
1537       *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
1538       break;
1539
1540     case DBUS_TYPE_INT64:
1541     case DBUS_TYPE_UINT64:
1542     case DBUS_TYPE_OBJECT_ID:
1543     case DBUS_TYPE_DOUBLE:
1544       
1545       *end_pos = _DBUS_ALIGN_VALUE (pos, 8) + 8;
1546       break;
1547
1548     case DBUS_TYPE_STRING:
1549       {
1550         int len;
1551         
1552         /* Demarshal the length */
1553         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1554
1555         *end_pos = pos + len + 1;
1556       }
1557       break;
1558
1559     case DBUS_TYPE_NAMED:
1560       {
1561         int len;
1562         
1563         /* Demarshal the string length */
1564         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1565
1566         *end_pos = pos + len + 1;
1567         
1568         /* Demarshal the data length */
1569         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1570
1571         *end_pos = pos + len;
1572       }
1573       break;
1574       
1575     case DBUS_TYPE_ARRAY:
1576       {
1577         int len;
1578
1579         /* Demarshal the length  */
1580         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1581         
1582         *end_pos = pos + len;
1583       }
1584       break;
1585
1586     case DBUS_TYPE_DICT:
1587       {
1588         int len;
1589
1590         /* Demarshal the length */
1591         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1592         
1593         *end_pos = pos + len;
1594       }
1595       break;
1596       
1597     default:
1598       _dbus_warn ("Unknown message arg type %d\n", type);
1599       _dbus_assert_not_reached ("Unknown message argument type\n");
1600       return FALSE;
1601     }
1602
1603   if (*end_pos > _dbus_string_get_length (str))
1604     return FALSE;
1605   
1606   return TRUE;
1607 }
1608
1609 /**
1610  * Demarshals and validates a length; returns < 0 if the validation
1611  * fails. The length is required to be small enough that
1612  * len*sizeof(double) will not overflow, and small enough to fit in a
1613  * signed integer. DOES NOT check whether the length points
1614  * beyond the end of the string, because it doesn't know the
1615  * size of array elements.
1616  *
1617  * @param str the string
1618  * @param byte_order the byte order
1619  * @param pos the unaligned string position (snap to next aligned)
1620  * @param new_pos return location for new position.
1621  */
1622 static int
1623 demarshal_and_validate_len (const DBusString *str,
1624                             int               byte_order,
1625                             int               pos,
1626                             int              *new_pos)
1627 {
1628   int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1629   unsigned int len;
1630
1631   _dbus_assert (new_pos != NULL);
1632   
1633   if ((align_4 + 4) > _dbus_string_get_length (str))
1634     {
1635       _dbus_verbose ("not enough room in message for array length\n");
1636       return -1;
1637     }
1638   
1639   if (!_dbus_string_validate_nul (str, pos,
1640                                   align_4 - pos))
1641     {
1642       _dbus_verbose ("array length alignment padding not initialized to nul\n");
1643       return -1;
1644     }
1645
1646   len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
1647
1648   /* note that the len is the number of bytes, so we need it to be
1649    * at least SIZE_T_MAX, but make it smaller just to keep things
1650    * sane.  We end up using ints for most sizes to avoid unsigned mess
1651    * so limit to maximum 32-bit signed int divided by at least 8, more
1652    * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
1653    */  
1654 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
1655   if (len > MAX_ARRAY_LENGTH)
1656     {
1657       _dbus_verbose ("array length %u exceeds maximum of %u\n",
1658                      len, MAX_ARRAY_LENGTH);
1659       return -1;
1660     }
1661   else
1662     return (int) len;
1663 }
1664
1665 static dbus_bool_t
1666 validate_string (const DBusString *str,
1667                  int               pos,
1668                  int               len_without_nul,
1669                  int              *end_pos)
1670 {
1671   *end_pos = pos + len_without_nul + 1;
1672   
1673   if (*end_pos > _dbus_string_get_length (str))
1674     {
1675       _dbus_verbose ("string length outside length of the message\n");
1676       return FALSE;
1677     }
1678   
1679   if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
1680     {
1681       _dbus_verbose ("string arg not nul-terminated\n");
1682       return FALSE;
1683     }
1684   
1685   if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
1686     {
1687       _dbus_verbose ("string is not valid UTF-8\n");
1688       return FALSE;
1689     }
1690
1691   return TRUE;
1692 }   
1693
1694 /**
1695  * Validates and returns a typecode at a specific position
1696  * in the message
1697  *
1698  * @param str a string
1699  * @param type the type of the argument
1700  * @param pos the pos where the typecode starts
1701  * @param end_pos pointer where the position right
1702  * after the end position will follow
1703  * @returns #TRUE if the type is valid.
1704  */
1705 dbus_bool_t
1706 _dbus_marshal_validate_type   (const DBusString *str,
1707                                int               pos,
1708                                int              *type,
1709                                int              *end_pos)
1710 {
1711   const char *data;
1712   
1713   if (pos >= _dbus_string_get_length (str))
1714     return FALSE;
1715
1716   data = _dbus_string_get_const_data_len (str, pos, 1);
1717
1718   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1719     {
1720       *type = *data;
1721       if (end_pos != NULL)
1722         *end_pos = pos + 1;
1723       return TRUE;
1724     }
1725   
1726   return FALSE;
1727 }
1728
1729 /* Faster validator for array data that doesn't call
1730  * validate_arg for each value
1731  */
1732 static dbus_bool_t
1733 validate_array_data (const DBusString *str,
1734                      int               byte_order,
1735                      int               depth,
1736                      int               type,
1737                      int               array_type_pos,
1738                      int               pos,
1739                      int              *new_pos,
1740                      int               end)
1741 {
1742   switch (type)
1743     {
1744     case DBUS_TYPE_INVALID:
1745       return FALSE;
1746       break;
1747
1748     case DBUS_TYPE_NIL:
1749       break;
1750
1751     case DBUS_TYPE_STRING:
1752     case DBUS_TYPE_NAMED:      
1753     case DBUS_TYPE_ARRAY:
1754     case DBUS_TYPE_DICT:
1755       /* This clean recursion to validate_arg is what we
1756        * are doing logically for all types, but we don't
1757        * really want to call validate_arg for every byte
1758        * in a byte array, so the primitive types are
1759        * special-cased.
1760        */
1761       while (pos < end)
1762         {
1763           if (!_dbus_marshal_validate_arg (str, byte_order, depth,
1764                                            type, array_type_pos, pos, &pos))
1765             return FALSE;
1766         }
1767       break;
1768       
1769     case DBUS_TYPE_BYTE:
1770       pos = end;
1771       break;
1772       
1773     case DBUS_TYPE_BOOLEAN:
1774       while (pos < end)
1775         {
1776           unsigned char c;
1777           
1778           c = _dbus_string_get_byte (str, pos);
1779           
1780           if (!(c == 0 || c == 1))
1781             {
1782               _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
1783               return FALSE;
1784             }
1785           
1786           ++pos;
1787         }
1788       break;
1789       
1790     case DBUS_TYPE_INT32:
1791     case DBUS_TYPE_UINT32:
1792       /* Call validate arg one time to check alignment padding
1793        * at start of array
1794        */
1795       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
1796                                        type, array_type_pos, pos, &pos))
1797         return FALSE;
1798       pos = _DBUS_ALIGN_VALUE (end, 4);
1799       break;
1800
1801     case DBUS_TYPE_INT64:
1802     case DBUS_TYPE_UINT64:
1803     case DBUS_TYPE_DOUBLE:
1804     case DBUS_TYPE_OBJECT_ID:
1805       /* Call validate arg one time to check alignment padding
1806        * at start of array
1807        */
1808       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
1809                                        type, array_type_pos, pos, &pos))
1810         return FALSE;
1811       pos = _DBUS_ALIGN_VALUE (end, 8);
1812       break;
1813       
1814     default:
1815       _dbus_verbose ("Unknown message arg type %d\n", type);
1816       return FALSE;
1817     }
1818
1819   *new_pos = pos;
1820
1821   return TRUE;
1822 }
1823
1824 /** 
1825  * Validates an argument of a specific type, checking that it
1826  * is well-formed, for example no ludicrous length fields, strings
1827  * are nul-terminated, etc.
1828  * Returns the end position of the argument in end_pos, and
1829  * returns #TRUE if a valid arg begins at "pos"
1830  *
1831  * @todo security: need to audit this function.
1832  *
1833  * @todo For array types that can't be invalid, we should not
1834  * walk the whole array validating it. e.g. just skip all the
1835  * int values in an int array.
1836  * 
1837  * @param str a string
1838  * @param byte_order the byte order to use
1839  * @param depth current recursion depth, to prevent excessive recursion
1840  * @param type the type of the argument
1841  * @param array_type_pos the position of the current array type, or
1842  *        -1 if not in an array
1843  * @param pos the pos where the arg starts
1844  * @param end_pos pointer where the position right
1845  * after the end position will follow
1846  * @returns #TRUE if the arg is valid.
1847  */
1848 dbus_bool_t
1849 _dbus_marshal_validate_arg (const DBusString *str,
1850                             int               byte_order,
1851                             int               depth,
1852                             int               type,
1853                             int               array_type_pos,
1854                             int               pos,
1855                             int              *end_pos)
1856 {
1857   if (pos > _dbus_string_get_length (str))
1858     {
1859       _dbus_verbose ("Validation went off the end of the message\n");
1860       return FALSE;
1861     }
1862
1863 #define MAX_VALIDATION_DEPTH 32
1864   
1865   if (depth > MAX_VALIDATION_DEPTH)
1866     {
1867       _dbus_verbose ("Maximum recursion depth reached validating message\n");
1868       return FALSE;
1869     }
1870   
1871   switch (type)
1872     {
1873     case DBUS_TYPE_INVALID:
1874       return FALSE;
1875       break;
1876
1877     case DBUS_TYPE_NIL:
1878       *end_pos = pos;
1879       break;
1880
1881     case DBUS_TYPE_BYTE:
1882       if (1 > _dbus_string_get_length (str) - pos)
1883         {
1884           _dbus_verbose ("no room for byte value\n");
1885           return FALSE;
1886         }
1887         
1888       *end_pos = pos + 1;
1889       break;
1890       
1891     case DBUS_TYPE_BOOLEAN:
1892       {
1893         unsigned char c;
1894
1895         if (1 > _dbus_string_get_length (str) - pos)
1896           {
1897             _dbus_verbose ("no room for boolean value\n");
1898             return FALSE;
1899           }
1900         
1901         c = _dbus_string_get_byte (str, pos);
1902
1903         if (!(c == 0 || c == 1))
1904           {
1905             _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
1906             return FALSE;
1907           }
1908         
1909         *end_pos = pos + 1;
1910       }
1911       break;
1912       
1913     case DBUS_TYPE_INT32:
1914     case DBUS_TYPE_UINT32:
1915       {
1916         int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1917         
1918         if (!_dbus_string_validate_nul (str, pos,
1919                                         align_4 - pos))
1920           {
1921             _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
1922             return FALSE;
1923           }
1924
1925         *end_pos = align_4 + 4;
1926       }
1927       break;
1928
1929     case DBUS_TYPE_INT64:
1930     case DBUS_TYPE_UINT64:      
1931     case DBUS_TYPE_DOUBLE:
1932     case DBUS_TYPE_OBJECT_ID:
1933       {
1934         int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
1935
1936         _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
1937         
1938         if (!_dbus_string_validate_nul (str, pos,
1939                                         align_8 - pos))
1940           {
1941             _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul\n");
1942             return FALSE;
1943           }
1944
1945         *end_pos = align_8 + 8;
1946       }
1947       break;
1948
1949     case DBUS_TYPE_STRING:
1950       {
1951         int len;
1952
1953         /* Demarshal the length, which does NOT include
1954          * nul termination
1955          */
1956         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1957         if (len < 0)
1958           return FALSE;
1959
1960         if (!validate_string (str, pos, len, end_pos))
1961           return FALSE;
1962       }
1963       break;
1964
1965     case DBUS_TYPE_NAMED:
1966       {
1967         int len;
1968
1969         /* Demarshal the string length, which does NOT include
1970          * nul termination
1971          */
1972         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1973         if (len < 0)
1974           return FALSE;
1975
1976         if (!validate_string (str, pos, len, &pos))
1977           return FALSE;
1978
1979         /* Validate data */
1980         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1981         if (len < 0)
1982           return FALSE;
1983
1984         *end_pos = pos + len;
1985       }
1986       break;
1987       
1988     case DBUS_TYPE_ARRAY:
1989       {
1990         int len;
1991         int end;
1992         int array_type;
1993
1994         if (array_type_pos == -1)
1995           {
1996             array_type_pos = pos;
1997
1998             do
1999               {
2000                 if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
2001                   {
2002                     _dbus_verbose ("invalid array type\n");
2003                     return FALSE;
2004                   }
2005                 
2006                 /* NIL values take up no space, so you couldn't iterate over an array of them.
2007                  * array of nil seems useless anyway; the useful thing might be array of
2008                  * (nil OR string) but we have no framework for that.
2009                  */
2010                 if (array_type == DBUS_TYPE_NIL)
2011                   {
2012                     _dbus_verbose ("array of NIL is not allowed\n");
2013                     return FALSE;
2014                   }
2015               }
2016             while (array_type == DBUS_TYPE_ARRAY);
2017           }
2018         else
2019           array_type_pos++;
2020
2021         if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
2022           {
2023             _dbus_verbose ("invalid array type\n");
2024             return FALSE;
2025           }
2026         
2027         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2028         if (len < 0)
2029           return FALSE;
2030
2031         if (len > _dbus_string_get_length (str) - pos)
2032           {
2033             _dbus_verbose ("array length outside length of the message\n");
2034             return FALSE;
2035           }
2036         
2037         end = pos + len;
2038
2039         if (!validate_array_data (str, byte_order, depth + 1,
2040                                   array_type, array_type_pos,
2041                                   pos, &pos, end))
2042           return FALSE;
2043
2044         if (pos < end)
2045           {
2046             /* This should not be able to happen, as long as validate_arg moves forward;
2047              * but the check is here just to be paranoid.
2048              */
2049             _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
2050                            len, end - pos);
2051             return FALSE;
2052           }
2053         
2054         if (pos > end)
2055           {
2056             _dbus_verbose ("array contents exceeds array length %d by %d\n", len, pos - end);
2057             return FALSE;
2058           }
2059
2060         *end_pos = pos;
2061       }
2062       break;
2063
2064     case DBUS_TYPE_DICT:
2065       {
2066         int dict_type;
2067         int len;
2068         int end;
2069         
2070         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2071         if (len < 0)
2072           return FALSE;
2073
2074         if (len > _dbus_string_get_length (str) - pos)
2075           {
2076             _dbus_verbose ("dict length outside length of the message\n");
2077             return FALSE;
2078           }
2079         
2080         end = pos + len;
2081         
2082         while (pos < end)
2083           {
2084             /* Validate name */
2085             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2086                                              DBUS_TYPE_STRING, -1, pos, &pos))
2087               return FALSE;
2088             
2089             if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
2090               {
2091                 _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
2092                 return FALSE;
2093               }
2094             
2095             /* Validate element */
2096             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2097                                              dict_type, -1, pos, &pos))
2098               return FALSE;
2099           }
2100         
2101         if (pos > end)
2102           {
2103             _dbus_verbose ("dict contents exceed stated dict length\n");
2104             return FALSE;
2105           }
2106         
2107         *end_pos = pos;
2108       }
2109       break;
2110       
2111     default:
2112       _dbus_verbose ("Unknown message arg type %d\n", type);
2113       return FALSE;
2114     }
2115
2116   if (*end_pos > _dbus_string_get_length (str))
2117     return FALSE;
2118   
2119   return TRUE;
2120 }
2121
2122
2123 /**
2124  * If in verbose mode, print a block of binary data.
2125  *
2126  * @todo right now it prints even if not in verbose mode
2127  * 
2128  * @param data the data
2129  * @param len the length of the data
2130  */
2131 void
2132 _dbus_verbose_bytes (const unsigned char *data,
2133                      int                  len)
2134 {
2135   int i;
2136   const unsigned char *aligned;
2137
2138   _dbus_assert (len >= 0);
2139   
2140   /* Print blanks on first row if appropriate */
2141   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
2142   if (aligned > data)
2143     aligned -= 4;
2144   _dbus_assert (aligned <= data);
2145
2146   if (aligned != data)
2147     {
2148       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 
2149       while (aligned != data)
2150         {
2151           _dbus_verbose ("    ");
2152           ++aligned;
2153         }
2154     }
2155
2156   /* now print the bytes */
2157   i = 0;
2158   while (i < len)
2159     {
2160       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2161         {
2162           _dbus_verbose ("%4d\t%p: ",
2163                    i, &data[i]);
2164         }
2165       
2166       if (data[i] >= 32 &&
2167           data[i] <= 126)
2168         _dbus_verbose (" '%c' ", data[i]);
2169       else
2170         _dbus_verbose ("0x%s%x ",
2171                  data[i] <= 0xf ? "0" : "", data[i]);
2172
2173       ++i;
2174
2175       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2176         {
2177           if (i > 3)
2178             _dbus_verbose ("BE: %d LE: %d",
2179                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
2180                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
2181
2182           if (i > 7 && 
2183               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
2184             {
2185               _dbus_verbose (" dbl: %g",
2186                              *(double*)&data[i-8]);
2187             }
2188           
2189           _dbus_verbose ("\n");
2190         }
2191     }
2192
2193   _dbus_verbose ("\n");
2194 }
2195
2196 /**
2197  * Dump the given part of the string to verbose log.
2198  *
2199  * @param str the string
2200  * @param start the start of range to dump
2201  * @param len length of range
2202  */
2203 void
2204 _dbus_verbose_bytes_of_string (const DBusString    *str,
2205                                int                  start,
2206                                int                  len)
2207 {
2208   const char *d;
2209   int real_len;
2210
2211   real_len = _dbus_string_get_length (str);
2212
2213   _dbus_assert (start >= 0);
2214   
2215   if (start > real_len)
2216     {
2217       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
2218                      start, len, real_len);
2219       return;
2220     }
2221
2222   if ((start + len) > real_len)
2223     {
2224       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
2225                      start, len, real_len);
2226       len = real_len - start;
2227     }
2228   
2229   d = _dbus_string_get_const_data_len (str, start, len);
2230
2231   _dbus_verbose_bytes (d, len);
2232 }
2233
2234 /** @} */
2235
2236 #ifdef DBUS_BUILD_TESTS
2237 #include "dbus-test.h"
2238 #include <stdio.h>
2239
2240 dbus_bool_t
2241 _dbus_marshal_test (void)
2242 {
2243   DBusString str;
2244   char *tmp1, *tmp2;
2245   int pos = 0, len;
2246   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
2247 #ifdef DBUS_HAVE_INT64
2248   dbus_int64_t array3[3] = { 0x123ffffffff, 0x456ffffffff, 0x789ffffffff }, *array4;
2249 #endif
2250   char *s;
2251   DBusString t;
2252   DBusObjectID obj_id, obj_id2;
2253   
2254   if (!_dbus_string_init (&str))
2255     _dbus_assert_not_reached ("failed to init string");
2256
2257   /* Marshal doubles */
2258   if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
2259     _dbus_assert_not_reached ("could not marshal double value");
2260   if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
2261     _dbus_assert_not_reached ("demarshal failed");
2262
2263   if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
2264     _dbus_assert_not_reached ("could not marshal double value");
2265   if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
2266     _dbus_assert_not_reached ("demarshal failed");
2267   
2268   /* Marshal signed integers */
2269   if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
2270     _dbus_assert_not_reached ("could not marshal signed integer value");
2271   if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
2272     _dbus_assert_not_reached ("demarshal failed");
2273
2274   if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
2275     _dbus_assert_not_reached ("could not marshal signed integer value");
2276   if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
2277     _dbus_assert_not_reached ("demarshal failed");
2278   
2279   /* Marshal unsigned integers */
2280   if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
2281     _dbus_assert_not_reached ("could not marshal signed integer value");
2282   if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
2283     _dbus_assert_not_reached ("demarshal failed");
2284   
2285   if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
2286     _dbus_assert_not_reached ("could not marshal signed integer value");
2287   if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
2288     _dbus_assert_not_reached ("demarshal failed");
2289
2290 #ifdef DBUS_HAVE_INT64
2291   /* Marshal signed integers */
2292   if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2293     _dbus_assert_not_reached ("could not marshal signed integer value");
2294   if (!_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_INT64_CONSTANT (-0x123456789abc7))
2295     _dbus_assert_not_reached ("demarshal failed");
2296
2297   if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2298     _dbus_assert_not_reached ("could not marshal signed integer value");
2299   if (!_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_INT64_CONSTANT (-0x123456789abc7))
2300     _dbus_assert_not_reached ("demarshal failed");
2301   
2302   /* Marshal unsigned integers */
2303   if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2304     _dbus_assert_not_reached ("could not marshal signed integer value");
2305   if (!(_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2306     _dbus_assert_not_reached ("demarshal failed");
2307   
2308   if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2309     _dbus_assert_not_reached ("could not marshal signed integer value");
2310   if (!(_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2311     _dbus_assert_not_reached ("demarshal failed");
2312 #endif /* DBUS_HAVE_INT64 */
2313
2314   /* Marshal object IDs */
2315   dbus_object_id_set_high_bits (&obj_id, 0xfffe);
2316   dbus_object_id_set_low_bits (&obj_id, 0xaacc);
2317
2318   if (!_dbus_marshal_object_id (&str, DBUS_BIG_ENDIAN, &obj_id))
2319     _dbus_assert_not_reached ("could not marshal object ID value");
2320   _dbus_demarshal_object_id (&str, DBUS_BIG_ENDIAN, pos, &pos, &obj_id2);
2321   if (!dbus_object_id_equal (&obj_id, &obj_id2))
2322     _dbus_assert_not_reached ("demarshal failed");
2323
2324   if (!_dbus_marshal_object_id (&str, DBUS_LITTLE_ENDIAN, &obj_id))
2325     _dbus_assert_not_reached ("could not marshal object ID value");
2326   _dbus_demarshal_object_id (&str, DBUS_LITTLE_ENDIAN, pos, &pos, &obj_id2);
2327   if (!dbus_object_id_equal (&obj_id, &obj_id2))
2328     _dbus_assert_not_reached ("demarshal failed");
2329   
2330   /* Marshal strings */
2331   tmp1 = "This is the dbus test string";
2332   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
2333     _dbus_assert_not_reached ("could not marshal string");
2334   tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
2335   if (!strcmp (tmp1, tmp2) == 0)
2336     _dbus_assert_not_reached ("demarshal failed");
2337   dbus_free (tmp2);
2338
2339   tmp1 = "This is the dbus test string";
2340   if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
2341     _dbus_assert_not_reached ("could not marshal string");
2342   tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
2343   if (!strcmp (tmp1, tmp2) == 0)
2344     _dbus_assert_not_reached ("demarshal failed");
2345   dbus_free (tmp2);
2346
2347   /* Marshal signed integer arrays */
2348   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
2349     _dbus_assert_not_reached ("could not marshal integer array");
2350   if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len))
2351     _dbus_assert_not_reached ("could not demarshal integer array");
2352
2353   if (len != 3)
2354     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2355   dbus_free (array2);
2356
2357 #ifdef DBUS_HAVE_INT64
2358   /* Marshal 64-bit signed integer arrays */
2359   if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3))
2360     _dbus_assert_not_reached ("could not marshal integer array");
2361   if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len))
2362     _dbus_assert_not_reached ("could not demarshal integer array");
2363
2364   if (len != 3)
2365     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2366   dbus_free (array4);
2367
2368   /* set/pack 64-bit integers */
2369   _dbus_string_set_length (&str, 8);
2370
2371   /* signed little */
2372   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
2373                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2374   
2375   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2376                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2377                                     _dbus_string_get_const_data (&str)));
2378
2379   /* signed big */
2380   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
2381                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2382
2383   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2384                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2385                                     _dbus_string_get_const_data (&str)));
2386
2387   /* signed little pack */
2388   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2389                     DBUS_LITTLE_ENDIAN,
2390                     _dbus_string_get_data (&str));
2391   
2392   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2393                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2394                                     _dbus_string_get_const_data (&str)));
2395
2396   /* signed big pack */
2397   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2398                     DBUS_BIG_ENDIAN,
2399                     _dbus_string_get_data (&str));
2400
2401   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2402                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2403                                     _dbus_string_get_const_data (&str)));
2404
2405   /* unsigned little */
2406   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
2407                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2408   
2409   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2410                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2411                                      _dbus_string_get_const_data (&str)));
2412
2413   /* unsigned big */
2414   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
2415                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2416
2417   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2418                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2419                                      _dbus_string_get_const_data (&str)));
2420
2421   /* unsigned little pack */
2422   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2423                      DBUS_LITTLE_ENDIAN,
2424                      _dbus_string_get_data (&str));
2425   
2426   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2427                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2428                                      _dbus_string_get_const_data (&str)));
2429
2430   /* unsigned big pack */
2431   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2432                      DBUS_BIG_ENDIAN,
2433                      _dbus_string_get_data (&str));
2434
2435   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2436                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2437                                      _dbus_string_get_const_data (&str)));
2438   
2439 #endif
2440
2441   /* set/pack 32-bit integers */
2442   _dbus_string_set_length (&str, 4);
2443
2444   /* signed little */
2445   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
2446                            0, -0x123456);
2447   
2448   _dbus_assert (-0x123456 ==
2449                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2450                                     _dbus_string_get_const_data (&str)));
2451
2452   /* signed big */
2453   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
2454                            0, -0x123456);
2455
2456   _dbus_assert (-0x123456 ==
2457                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2458                                     _dbus_string_get_const_data (&str)));
2459
2460   /* signed little pack */
2461   _dbus_pack_int32 (-0x123456,
2462                     DBUS_LITTLE_ENDIAN,
2463                     _dbus_string_get_data (&str));
2464   
2465   _dbus_assert (-0x123456 ==
2466                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2467                                     _dbus_string_get_const_data (&str)));
2468
2469   /* signed big pack */
2470   _dbus_pack_int32 (-0x123456,
2471                     DBUS_BIG_ENDIAN,
2472                     _dbus_string_get_data (&str));
2473
2474   _dbus_assert (-0x123456 ==
2475                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2476                                     _dbus_string_get_const_data (&str)));
2477
2478   /* unsigned little */
2479   _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
2480                             0, 0x123456);
2481   
2482   _dbus_assert (0x123456 ==
2483                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2484                                      _dbus_string_get_const_data (&str)));
2485
2486   /* unsigned big */
2487   _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
2488                             0, 0x123456);
2489
2490   _dbus_assert (0x123456 ==
2491                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2492                                      _dbus_string_get_const_data (&str)));
2493
2494   /* unsigned little pack */
2495   _dbus_pack_uint32 (0x123456,
2496                      DBUS_LITTLE_ENDIAN,
2497                      _dbus_string_get_data (&str));
2498   
2499   _dbus_assert (0x123456 ==
2500                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2501                                      _dbus_string_get_const_data (&str)));
2502
2503   /* unsigned big pack */
2504   _dbus_pack_uint32 (0x123456,
2505                      DBUS_BIG_ENDIAN,
2506                      _dbus_string_get_data (&str));
2507
2508   _dbus_assert (0x123456 ==
2509                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2510                                      _dbus_string_get_const_data (&str)));
2511
2512
2513   /* Strings */
2514   
2515   _dbus_string_set_length (&str, 0);
2516
2517   _dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN,
2518                         "Hello world");
2519   
2520   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2521   _dbus_assert (strcmp (s, "Hello world") == 0);
2522   dbus_free (s);
2523
2524   _dbus_string_init_const (&t, "Hello world foo");
2525   
2526   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2527                             &t, _dbus_string_get_length (&t));
2528   
2529   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2530   _dbus_assert (strcmp (s, "Hello world foo") == 0);
2531   dbus_free (s);
2532
2533   _dbus_string_init_const (&t, "Hello");
2534   
2535   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2536                             &t, _dbus_string_get_length (&t));
2537   
2538   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2539   _dbus_assert (strcmp (s, "Hello") == 0);
2540   dbus_free (s);
2541
2542   /* Strings (big endian) */
2543   
2544   _dbus_string_set_length (&str, 0);
2545
2546   _dbus_marshal_string (&str, DBUS_BIG_ENDIAN,
2547                         "Hello world");
2548   
2549   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2550   _dbus_assert (strcmp (s, "Hello world") == 0);
2551   dbus_free (s);
2552
2553   _dbus_string_init_const (&t, "Hello world foo");
2554   
2555   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
2556                             &t, _dbus_string_get_length (&t));
2557   
2558   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2559   _dbus_assert (strcmp (s, "Hello world foo") == 0);
2560   dbus_free (s);
2561
2562   _dbus_string_init_const (&t, "Hello");
2563   
2564   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
2565                             &t, _dbus_string_get_length (&t));
2566   
2567   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2568   _dbus_assert (strcmp (s, "Hello") == 0);
2569   dbus_free (s);
2570
2571   
2572   _dbus_string_free (&str);
2573       
2574   return TRUE;
2575 }
2576
2577 #endif /* DBUS_BUILD_TESTS */