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