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