2003-02-21 Anders Carlsson <andersca@codefactory.se>
[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  *
6  * Licensed under the Academic Free License version 1.2
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-marshal.h"
25 #include "dbus-internals.h"
26
27 #include <string.h>
28
29 /* from ORBit */
30 static void
31 swap_bytes (unsigned char *data,
32             unsigned int   len)
33 {
34   unsigned char *p1 = data;
35   unsigned char *p2 = data + len - 1;
36
37   while (p1 < p2)
38     {
39       unsigned char tmp = *p1;
40       *p1 = *p2;
41       *p2 = tmp;
42
43       --p2;
44       ++p1;
45     }
46 }
47
48 /**
49  * @defgroup DBusMarshal marshaling and unmarshaling
50  * @ingroup  DBusInternals
51  * @brief functions to marshal/unmarshal data from the wire
52  *
53  * Types and functions related to converting primitive data types from
54  * wire format to native machine format, and vice versa.
55  *
56  * @{
57  */
58
59 /**
60  * Unpacks a 32 bit unsigned integer from a data pointer
61  *
62  * @param byte_order The byte order to use
63  * @param data the data pointer
64  * @returns the integer
65  */
66 dbus_uint32_t
67 _dbus_unpack_uint32 (int                  byte_order,
68                      const unsigned char *data)
69 {
70   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
71   
72   if (byte_order == DBUS_LITTLE_ENDIAN)
73     return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
74   else
75     return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
76 }  
77
78 /**
79  * Unpacks a 32 bit signed integer from a data pointer
80  *
81  * @param byte_order The byte order to use
82  * @param data the data pointer
83  * @returns the integer
84  */
85 dbus_int32_t
86 _dbus_unpack_int32 (int                  byte_order,
87                     const unsigned char *data)
88 {
89   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
90   
91   if (byte_order == DBUS_LITTLE_ENDIAN)
92     return DBUS_INT32_FROM_LE (*(dbus_int32_t*)data);
93   else
94     return DBUS_INT32_FROM_BE (*(dbus_int32_t*)data);
95 }
96
97 /**
98  * Packs a 32 bit unsigned integer into a data pointer.
99  *
100  * @param value the value
101  * @param byte_order the byte order to use
102  * @param data the data pointer
103  */
104 void
105 _dbus_pack_uint32 (dbus_uint32_t   value,
106                    int             byte_order,
107                    unsigned char  *data)
108 {
109   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
110   
111   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
112     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);       
113   else
114     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
115 }
116
117 /**
118  * Packs a 32 bit signed integer into a data pointer.
119  *
120  * @param value the value
121  * @param byte_order the byte order to use
122  * @param data the data pointer
123  */
124 void
125 _dbus_pack_int32 (dbus_int32_t   value,
126                   int            byte_order,
127                   unsigned char *data)
128 {
129   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
130   
131   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
132     *((dbus_int32_t*)(data)) = DBUS_INT32_TO_LE (value);       
133   else
134     *((dbus_int32_t*)(data)) = DBUS_INT32_TO_BE (value);
135 }
136
137 /**
138  * Sets the 4 bytes at the given offset to a marshaled signed integer,
139  * replacing anything found there previously.
140  *
141  * @param str the string to write the marshalled int to
142  * @param offset the byte offset where int should be written
143  * @param byte_order the byte order to use
144  * @param value the value
145  * 
146  */
147 void
148 _dbus_marshal_set_int32 (DBusString          *str,
149                          int                  byte_order,
150                          int                  offset,
151                          dbus_int32_t         value)
152 {
153   char *data;
154   
155   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
156                 byte_order == DBUS_BIG_ENDIAN);
157   
158   _dbus_string_get_data_len (str, &data, offset, 4);
159
160   _dbus_pack_int32 (value, byte_order, data);
161 }
162
163 /**
164  * Sets the 4 bytes at the given offset to a marshaled unsigned
165  * integer, replacing anything found there previously.
166  *
167  * @param str the string to write the marshalled int to
168  * @param offset the byte offset where int should be written
169  * @param byte_order the byte order to use
170  * @param value the value
171  * 
172  */
173 void
174 _dbus_marshal_set_uint32 (DBusString          *str,
175                           int                  byte_order,
176                           int                  offset,
177                           dbus_uint32_t        value)
178 {
179   char *data;
180   
181   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
182                 byte_order == DBUS_BIG_ENDIAN);
183   
184   _dbus_string_get_data_len (str, &data, offset, 4);
185
186   _dbus_pack_uint32 (value, byte_order, data);
187 }
188
189 /**
190  * Sets the existing marshaled string at the given offset with
191  * a new marshaled string. The given offset must point to
192  * an existing string or the wrong length will be deleted
193  * and replaced with the new string.
194  *
195  * @param str the string to write the marshalled string to
196  * @param offset the byte offset where string should be written
197  * @param byte_order the byte order to use
198  * @param value the value
199  * @returns #TRUE on success
200  * 
201  */
202 dbus_bool_t
203 _dbus_marshal_set_string (DBusString          *str,
204                           int                  byte_order,
205                           int                  offset,
206                           const DBusString    *value)
207 {
208   int old_len;
209   int new_len;
210   
211   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
212                 byte_order == DBUS_BIG_ENDIAN);
213   
214   old_len = _dbus_demarshal_uint32 (str, byte_order,
215                                     offset, NULL);
216
217   new_len = _dbus_string_get_length (value);
218   
219   if (!_dbus_string_replace_len (value, 0, new_len,
220                                  str, offset + 4, old_len))
221     return FALSE;
222
223   _dbus_marshal_set_uint32 (str, byte_order,
224                             offset, new_len);
225
226   return TRUE;
227 }
228
229 /**
230  * Marshals a double value.
231  *
232  * @param str the string to append the marshalled value to
233  * @param byte_order the byte order to use
234  * @param value the value
235  * @returns #TRUE on success
236  */
237 dbus_bool_t
238 _dbus_marshal_double (DBusString *str,
239                       int         byte_order,
240                       double      value)
241 {
242   _dbus_assert (sizeof (double) == 8);
243
244   if (!_dbus_string_align_length (str, sizeof (double)))
245     return FALSE;
246   
247   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
248     swap_bytes ((unsigned char *)&value, sizeof (double));
249
250   return _dbus_string_append_len (str, (const char *)&value, sizeof (double));
251 }
252
253 /**
254  * Marshals a 32 bit signed integer value.
255  *
256  * @param str the string to append the marshalled value to
257  * @param byte_order the byte order to use
258  * @param value the value
259  * @returns #TRUE on success
260  */
261 dbus_bool_t
262 _dbus_marshal_int32  (DBusString   *str,
263                       int           byte_order,
264                       dbus_int32_t  value)
265 {
266   if (!_dbus_string_align_length (str, sizeof (dbus_int32_t)))
267     return FALSE;
268   
269   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
270     value = DBUS_INT32_SWAP_LE_BE (value);
271
272   return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_int32_t));
273 }
274
275 /**
276  * Marshals a 32 bit unsigned integer value.
277  *
278  * @param str the string to append the marshalled value to
279  * @param byte_order the byte order to use
280  * @param value the value
281  * @returns #TRUE on success
282  */
283 dbus_bool_t
284 _dbus_marshal_uint32 (DBusString    *str,
285                       int            byte_order,
286                       dbus_uint32_t  value)
287 {
288   if (!_dbus_string_align_length (str, sizeof (dbus_uint32_t)))
289     return FALSE;
290   
291   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
292     value = DBUS_UINT32_SWAP_LE_BE (value);
293
294   return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_uint32_t));
295 }
296
297 /**
298  * Marshals a UTF-8 string
299  *
300  * @param str the string to append the marshalled value to
301  * @param byte_order the byte order to use
302  * @param value the string
303  * @returns #TRUE on success
304  */
305 dbus_bool_t
306 _dbus_marshal_string (DBusString    *str,
307                       int            byte_order,
308                       const char    *value)
309 {
310   int len, old_string_len;
311
312   old_string_len = _dbus_string_get_length (str);
313   
314   len = strlen (value);
315
316   if (!_dbus_marshal_uint32 (str, byte_order, len))
317     {
318       /* Restore the previous length */
319       _dbus_string_set_length (str, old_string_len);
320
321       return FALSE;
322     }
323
324   return _dbus_string_append_len (str, value, len + 1);
325 }
326
327 /**
328  * Marshals a byte array
329  *
330  * @param str the string to append the marshalled value to
331  * @param byte_order the byte order to use
332  * @param value the array
333  * @param len number of elements in the array
334  * @returns #TRUE on success
335  */
336 dbus_bool_t
337 _dbus_marshal_byte_array (DBusString          *str,
338                           int                  byte_order,
339                           const unsigned char *value,
340                           int                  len)
341 {
342   int old_string_len;
343
344   old_string_len = _dbus_string_get_length (str);
345   
346   if (!_dbus_marshal_uint32 (str, byte_order, len))
347     {
348       /* Restore the previous length */
349       _dbus_string_set_length (str, old_string_len);
350
351       return FALSE;
352     }
353
354   return _dbus_string_append_len (str, value, len);
355 }
356
357 /**
358  * Marshals a 32 bit signed integer array
359  *
360  * @param str the string to append the marshalled value to
361  * @param byte_order the byte order to use
362  * @param value the array
363  * @param len the length of the array
364  * @returns #TRUE on success
365  */
366 dbus_bool_t
367 _dbus_marshal_int32_array (DBusString         *str,
368                            int                 byte_order,
369                            const dbus_int32_t *value,
370                            int                 len)
371 {
372   int i, old_string_len;
373
374   old_string_len = _dbus_string_get_length (str);
375
376   if (!_dbus_marshal_uint32 (str, byte_order, len))
377     goto error;
378
379   for (i = 0; i < len; i++)
380     if (!_dbus_marshal_int32 (str, byte_order, value[i]))
381       goto error;
382
383   return TRUE;
384   
385  error:
386   /* Restore previous length */
387   _dbus_string_set_length (str, old_string_len);
388   
389   return FALSE;
390 }
391
392 /**
393  * Marshals a 32 bit unsigned integer array
394  *
395  * @param str the string to append the marshalled value to
396  * @param byte_order the byte order to use
397  * @param value the array
398  * @param len the length of the array
399  * @returns #TRUE on success
400  */
401 dbus_bool_t
402 _dbus_marshal_uint32_array (DBusString          *str,
403                             int                  byte_order,
404                             const dbus_uint32_t  *value,
405                             int                  len)
406 {
407   int i, old_string_len;
408
409   old_string_len = _dbus_string_get_length (str);
410
411   if (!_dbus_marshal_uint32 (str, byte_order, len))
412     goto error;
413
414   for (i = 0; i < len; i++)
415     if (!_dbus_marshal_uint32 (str, byte_order, value[i]))
416       goto error;
417
418   return TRUE;
419   
420  error:
421   /* Restore previous length */
422   _dbus_string_set_length (str, old_string_len);
423   
424   return FALSE;  
425 }
426
427 /**
428  * Marshals a double array
429  *
430  * @param str the string to append the marshalled value to
431  * @param byte_order the byte order to use
432  * @param value the array
433  * @param len the length of the array
434  * @returns #TRUE on success
435  */
436 dbus_bool_t
437 _dbus_marshal_double_array (DBusString          *str,
438                             int                  byte_order,
439                             const double        *value,
440                             int                  len)
441 {
442   int i, old_string_len;
443
444   old_string_len = _dbus_string_get_length (str);
445
446   if (!_dbus_marshal_uint32 (str, byte_order, len))
447     goto error;
448
449   for (i = 0; i < len; i++)
450     if (!_dbus_marshal_double (str, byte_order, value[i]))
451       goto error;
452
453   return TRUE;
454   
455  error:
456   /* Restore previous length */
457   _dbus_string_set_length (str, old_string_len);
458   
459   return FALSE;    
460 }
461
462 /**
463  * Marshals a string array
464  *
465  * @param str the string to append the marshalled value to
466  * @param byte_order the byte order to use
467  * @param value the array
468  * @param len the length of the array
469  * @returns #TRUE on success
470  */
471 dbus_bool_t
472 _dbus_marshal_string_array (DBusString  *str,
473                             int          byte_order,
474                             const char **value,
475                             int          len)
476 {
477   int i, old_string_len;
478
479   old_string_len = _dbus_string_get_length (str);
480
481   if (!_dbus_marshal_uint32 (str, byte_order, len))
482     goto error;
483
484   for (i = 0; i < len; i++)
485     if (!_dbus_marshal_string (str, byte_order, value[i]))
486       goto error;
487
488   return TRUE;
489   
490  error:
491   /* Restore previous length */
492   _dbus_string_set_length (str, old_string_len);
493   
494   return FALSE;      
495 }
496
497 /**
498  * Demarshals a double.
499  *
500  * @param str the string containing the data
501  * @param byte_order the byte order
502  * @param pos the position in the string
503  * @param new_pos the new position of the string
504  * @returns the demarshaled double.
505  */
506 double
507 _dbus_demarshal_double (const DBusString  *str,
508                         int          byte_order,
509                         int          pos,
510                         int         *new_pos)
511 {
512   double retval;
513   const char *buffer;
514
515   pos = _DBUS_ALIGN_VALUE (pos, sizeof (double));
516
517   _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (double));
518
519   retval = *(double *)buffer;
520   
521   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
522     swap_bytes ((unsigned char *)&retval, sizeof (double));
523
524   if (new_pos)
525     *new_pos = pos + sizeof (double);
526   
527   return retval;  
528 }
529
530 /**
531  * Demarshals a 32 bit signed integer.
532  *
533  * @param str the string containing the data
534  * @param byte_order the byte order
535  * @param pos the position in the string
536  * @param new_pos the new position of the string
537  * @returns the demarshaled integer.
538  */
539 dbus_int32_t
540 _dbus_demarshal_int32  (const DBusString *str,
541                         int         byte_order,
542                         int         pos,
543                         int        *new_pos)
544 {
545   const char *buffer;
546
547   pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t));
548   
549   _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_int32_t));
550
551   if (new_pos)
552     *new_pos = pos + sizeof (dbus_int32_t);
553
554   return _dbus_unpack_int32 (byte_order, buffer);
555 }
556
557 /**
558  * Demarshals a 32 bit unsigned integer.
559  *
560  * @param str the string containing the data
561  * @param byte_order the byte order
562  * @param pos the position in the string
563  * @param new_pos the new position of the string
564  * @returns the demarshaled integer.
565  */
566 dbus_uint32_t
567 _dbus_demarshal_uint32  (const DBusString *str,
568                          int         byte_order,
569                          int         pos,
570                          int        *new_pos)
571 {
572   const char *buffer;
573
574   pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
575   
576   _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_uint32_t));
577
578   if (new_pos)
579     *new_pos = pos + sizeof (dbus_uint32_t);
580
581   return _dbus_unpack_uint32 (byte_order, buffer);
582 }
583
584 /**
585  * Demarshals an UTF-8 string.
586  *
587  * @todo Should we check the string to make sure
588  * that it's  valid UTF-8, and maybe "fix" the string
589  * if it's broken?
590  *
591  * @todo Should probably demarshal to a DBusString,
592  * having memcpy() in here is Evil(tm).
593  *
594  * @param str the string containing the data
595  * @param byte_order the byte order
596  * @param pos the position in the string
597  * @param new_pos the new position of the string
598  * @returns the demarshaled string.
599  */
600 char *
601 _dbus_demarshal_string (const DBusString *str,
602                         int         byte_order,
603                         int         pos,
604                         int        *new_pos)
605 {
606   int len;
607   char *retval;
608   const char *data;
609   
610   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
611
612   retval = dbus_malloc (len + 1);
613
614   if (!retval)
615     return NULL;
616
617   _dbus_string_get_const_data_len (str, &data, pos, len);
618
619   if (!data)
620     return NULL;
621
622   memcpy (retval, data, len + 1);
623
624   if (new_pos)
625     *new_pos = pos + len + 1;
626   
627   return retval;
628 }
629
630 /**
631  * Demarshals a byte array.
632  *
633  * @todo Should probably demarshal to a DBusString,
634  * having memcpy() in here is Evil(tm).
635  *
636  * @param str the string containing the data
637  * @param byte_order the byte order
638  * @param pos the position in the string
639  * @param new_pos the new position of the string
640  * @param array_len length of the demarshaled data
641  * @returns the demarshaled data.
642  */
643 unsigned char *
644 _dbus_demarshal_byte_array (const DBusString *str,
645                             int         byte_order,
646                             int         pos,
647                             int        *new_pos,
648                             int        *array_len)
649 {
650   int len;
651   unsigned char *retval;
652   const char *data;
653
654   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
655
656   retval = dbus_malloc (len);
657
658   if (!retval)
659     return NULL;
660
661   _dbus_string_get_const_data_len (str, &data, pos, len);
662
663   if (!data)
664     return NULL;
665
666   memcpy (retval, data, len);
667
668   if (new_pos)
669     *new_pos = pos + len;
670
671   if (array_len)
672     *array_len = len;
673
674   return retval;
675 }
676
677 /**
678  * Demarshals a 32 bit signed integer array.
679  *
680  * @param str the string containing the data
681  * @param byte_order the byte order
682  * @param pos the position in the string
683  * @param new_pos the new position of the string
684  * @param array_len length of the demarshaled data
685  * @returns the demarshaled data.
686  */
687 dbus_int32_t *
688 _dbus_demarshal_int32_array (const DBusString *str,
689                              int         byte_order,
690                              int         pos,
691                              int        *new_pos,
692                              int        *array_len)
693 {
694   int len, i;
695   dbus_int32_t *retval;
696   
697   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
698
699   retval = dbus_new (dbus_int32_t, len);
700
701   if (!retval)
702     return NULL;
703
704   for (i = 0; i < len; i++)
705     retval[i] = _dbus_demarshal_int32 (str, byte_order, pos, &pos);
706
707   if (new_pos)
708     *new_pos = pos;
709
710   if (array_len)
711     *array_len = len;
712   
713   return retval;
714 }
715
716 /**
717  * Demarshals a 32 bit unsigned integer array.
718  *
719  * @param str the string containing the data
720  * @param byte_order the byte order
721  * @param pos the position in the string
722  * @param new_pos the new position of the string
723  * @param array_len length of the demarshaled data
724  * @returns the demarshaled data.
725  */
726 dbus_uint32_t *
727 _dbus_demarshal_uint32_array (const DBusString *str,
728                               int         byte_order,
729                               int         pos,
730                               int        *new_pos,
731                               int        *array_len)
732 {
733   int len, i;
734   dbus_uint32_t *retval;
735   
736   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
737
738   retval = dbus_new (dbus_uint32_t, len);
739
740   if (!retval)
741     return NULL;
742
743   for (i = 0; i < len; i++)
744     retval[i] = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
745
746   if (new_pos)
747     *new_pos = pos;
748
749   if (array_len)
750     *array_len = len;
751   
752   return retval;  
753 }
754
755 /**
756  * Demarshals a double array.
757  *
758  * @param str the string containing the data
759  * @param byte_order the byte order
760  * @param pos the position in the string
761  * @param new_pos the new position of the string
762  * @param array_len length of the demarshaled data
763  * @returns the demarshaled data.
764  */
765 double *
766 _dbus_demarshal_double_array (const DBusString *str,
767                               int         byte_order,
768                               int         pos,
769                               int        *new_pos,
770                               int        *array_len)
771 {
772   int len, i;
773   double *retval;
774   
775   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
776
777   retval = dbus_new (double, len);
778
779   if (!retval)
780     return NULL;
781
782   for (i = 0; i < len; i++)
783     retval[i] = _dbus_demarshal_double (str, byte_order, pos, &pos);
784
785   if (new_pos)
786     *new_pos = pos;
787
788   if (array_len)
789     *array_len = len;
790   
791   return retval;  
792 }
793
794 /**
795  * Demarshals a string array.
796  *
797  * @param str the string containing the data
798  * @param byte_order the byte order
799  * @param pos the position in the string
800  * @param new_pos the new position of the string
801  * @param array_len length of the demarshaled data
802  * @returns the demarshaled data.
803  */
804 char **
805 _dbus_demarshal_string_array (const DBusString *str,
806                               int         byte_order,
807                               int         pos,
808                               int        *new_pos,
809                               int        *array_len)
810 {
811   int len, i, j;
812   char **retval;
813
814   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
815
816   retval = dbus_new (char *, len + 1);
817
818   if (!retval)
819     return NULL;
820
821   retval[len] = NULL;
822   
823   for (i = 0; i < len; i++)
824     {
825       retval[i] = _dbus_demarshal_string (str, byte_order, pos, &pos);
826
827       if (retval[i] == 0)
828         goto error;
829     }
830
831  if (new_pos)
832     *new_pos = pos;
833
834   if (array_len)
835     *array_len = len;
836   
837   return retval;
838
839  error:
840   for (j = 0; j < i; j++)
841     dbus_free (retval[i]);
842   dbus_free (retval);
843
844   return NULL;
845 }
846
847 /** 
848  * Returns the position right after the end of an argument.  PERFORMS
849  * NO VALIDATION WHATSOEVER. The message must have been previously
850  * validated.
851  *
852  * @param str a string
853  * @param byte_order the byte order to use
854  * @param pos the pos where the arg starts
855  * @param end_pos pointer where the position right
856  * after the end position will follow
857  * @returns TRUE if more data exists after the arg
858  */
859 dbus_bool_t
860 _dbus_marshal_get_arg_end_pos (const DBusString *str,
861                                int               byte_order,
862                                int               pos,
863                                int              *end_pos)
864 {
865   const char *data;
866
867   if (pos >= _dbus_string_get_length (str))
868     return FALSE;
869
870   _dbus_string_get_const_data_len (str, &data, pos, 1);
871   
872   switch (*data)
873     {
874     case DBUS_TYPE_INVALID:
875       return FALSE;
876       break;
877
878     case DBUS_TYPE_NIL:
879       *end_pos = pos + 1;
880       break;
881       
882     case DBUS_TYPE_INT32:
883       *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
884
885       break;
886
887     case DBUS_TYPE_UINT32:
888       *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
889
890       break;
891
892     case DBUS_TYPE_DOUBLE:
893       *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (double)) + sizeof (double);
894
895       break;
896
897     case DBUS_TYPE_STRING:
898       {
899         int len;
900
901         /* Demarshal the length */
902         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
903
904         *end_pos = pos + len + 1;
905       }
906       break;
907
908     case DBUS_TYPE_BYTE_ARRAY:
909       {
910         int len;
911
912         /* Demarshal the length */
913         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
914         
915         *end_pos = pos + len;
916       }
917       break;
918
919     case DBUS_TYPE_INT32_ARRAY:
920       {
921         int len, new_pos;
922
923         /* Demarshal the length */
924         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
925         
926         *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_int32_t))
927           + (len * sizeof (dbus_int32_t));
928       }
929       break;
930
931     case DBUS_TYPE_UINT32_ARRAY:
932       {
933         int len, new_pos;
934
935         /* Demarshal the length */
936         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
937
938         *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_uint32_t))
939           + (len * sizeof (dbus_uint32_t));
940       }
941       break;
942
943     case DBUS_TYPE_DOUBLE_ARRAY:
944       {
945         int len, new_pos;
946         
947         /* Demarshal the length */
948         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
949
950         *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (double))
951           + (len * sizeof (double));
952       }
953       break;
954       
955     case DBUS_TYPE_STRING_ARRAY:
956       {
957         int len, i;
958         
959         /* Demarshal the length */
960         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
961
962         for (i = 0; i < len; i++)
963           {
964             int str_len;
965             
966             /* Demarshal string length */
967             str_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
968             pos += str_len + 1;
969           }
970
971         *end_pos = pos;
972       }
973       break;
974       
975     default:
976       _dbus_warn ("Unknown message arg type %d\n", *data);
977       _dbus_assert_not_reached ("Unknown message argument type\n");
978       return FALSE;
979     }
980
981   if (*end_pos > _dbus_string_get_length (str))
982     return FALSE;
983   
984   return TRUE;
985 }
986
987 /**
988  * Demarshals and validates a length; returns < 0 if the validation
989  * fails. The length is required to be small enough that
990  * len*sizeof(double) will not overflow, and small enough to fit in a
991  * signed integer.
992  *
993  * @param str the string
994  * @param byte_order the byte order
995  * @param pos the unaligned string position (snap to next aligned)
996  * @param new_pos return location for new position.
997  */
998 static int
999 demarshal_and_validate_len (const DBusString *str,
1000                             int               byte_order,
1001                             int               pos,
1002                             int              *new_pos)
1003 {
1004   int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1005   unsigned int len;
1006   
1007   if ((align_4 + 4) >= _dbus_string_get_length (str))
1008     {
1009       _dbus_verbose ("not enough room in message for array length\n");
1010       return -1;
1011     }
1012   
1013   if (!_dbus_string_validate_nul (str, pos,
1014                                   align_4 - pos))
1015     {
1016       _dbus_verbose ("array length alignment padding not initialized to nul\n");
1017       return -1;
1018     }
1019
1020   len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
1021
1022   /* note that the len may be a number of doubles, so we need it to be
1023    * at least SIZE_T_MAX / 8, but make it smaller just to keep things
1024    * sane.  We end up using ints for most sizes to avoid unsigned mess
1025    * so limit to maximum 32-bit signed int divided by at least 8, more
1026    * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
1027    */  
1028 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
1029   if (len > MAX_ARRAY_LENGTH)
1030     {
1031       _dbus_verbose ("array length %u exceeds maximum of %u\n",
1032                      len, MAX_ARRAY_LENGTH);
1033       return -1;
1034     }
1035   else
1036     return (int) len;
1037 }
1038
1039 static dbus_bool_t
1040 validate_string (const DBusString *str,
1041                  int               pos,
1042                  int               len_without_nul,
1043                  int              *end_pos)
1044 {
1045   *end_pos = pos + len_without_nul + 1;
1046   
1047   if (*end_pos > _dbus_string_get_length (str))
1048     {
1049       _dbus_verbose ("string length outside length of the message\n");
1050       return FALSE;
1051     }
1052   
1053   if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
1054     {
1055       _dbus_verbose ("string arg not nul-terminated\n");
1056       return FALSE;
1057     }
1058   
1059   if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
1060     {
1061       _dbus_verbose ("string is not valid UTF-8\n");
1062       return FALSE;
1063     }
1064
1065   return TRUE;
1066 }   
1067
1068 /** 
1069  * Validates an argument, checking that it is well-formed, for example
1070  * no ludicrous length fields, strings are nul-terminated, etc.
1071  * Returns the end position of the argument in end_pos, and
1072  * returns #TRUE if a valid arg begins at "pos"
1073  *
1074  * @todo security: need to audit this function.
1075  * 
1076  * @param str a string
1077  * @param byte_order the byte order to use
1078  * @param pos the pos where the arg starts (offset of its typecode)
1079  * @param end_pos pointer where the position right
1080  * after the end position will follow
1081  * @returns #TRUE if the arg is valid.
1082  */
1083 dbus_bool_t
1084 _dbus_marshal_validate_arg (const DBusString *str,
1085                             int               byte_order,
1086                             int               pos,
1087                             int              *end_pos)
1088 {
1089   const char *data;
1090
1091   if (pos >= _dbus_string_get_length (str))
1092     return FALSE;
1093
1094   _dbus_string_get_const_data_len (str, &data, pos, 1);
1095   
1096   switch (*data)
1097     {
1098     case DBUS_TYPE_INVALID:
1099       return FALSE;
1100       break;
1101
1102     case DBUS_TYPE_NIL:
1103       *end_pos = pos + 1;
1104       break;
1105       
1106     case DBUS_TYPE_INT32:
1107     case DBUS_TYPE_UINT32:
1108       {
1109         int align_4 = _DBUS_ALIGN_VALUE (pos + 1, 4);
1110         
1111         if (!_dbus_string_validate_nul (str, pos + 1,
1112                                         align_4 - pos - 1))
1113           {
1114             _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
1115             return FALSE;
1116           }
1117
1118         *end_pos = align_4 + 4;
1119       }
1120       break;
1121
1122     case DBUS_TYPE_DOUBLE:
1123       {
1124         int align_8 = _DBUS_ALIGN_VALUE (pos + 1, 8);
1125
1126         _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
1127         
1128         if (!_dbus_string_validate_nul (str, pos + 1,
1129                                         align_8 - pos - 1))
1130           {
1131             _dbus_verbose ("double alignment padding not initialized to nul\n");
1132             return FALSE;
1133           }
1134
1135         *end_pos = align_8 + 8;
1136       }
1137       break;
1138
1139     case DBUS_TYPE_STRING:
1140       {
1141         int len;
1142
1143         /* Demarshal the length, which does NOT include
1144          * nul termination
1145          */
1146         len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
1147         if (len < 0)
1148           return FALSE;
1149
1150         if (!validate_string (str, pos, len, end_pos))
1151           return FALSE;
1152       }
1153       break;
1154
1155     case DBUS_TYPE_BYTE_ARRAY:
1156       {
1157         int len;
1158
1159         len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
1160         if (len < 0)
1161           return FALSE;
1162         
1163         *end_pos = pos + len;
1164       }
1165       break;
1166
1167     case DBUS_TYPE_INT32_ARRAY:
1168     case DBUS_TYPE_UINT32_ARRAY:
1169       {
1170         int len;
1171
1172         len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
1173         if (len < 0)
1174           return FALSE;
1175
1176         _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned int) pos);
1177         
1178         *end_pos = pos + len * 4;
1179       }
1180       break;
1181
1182     case DBUS_TYPE_DOUBLE_ARRAY:
1183       {
1184         int len;
1185         int align_8;
1186
1187         len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
1188         if (len < 0)
1189           return FALSE;
1190
1191         align_8 = _DBUS_ALIGN_VALUE (pos, 8);
1192         if (!_dbus_string_validate_nul (str, pos,
1193                                         align_8 - pos))
1194           {
1195             _dbus_verbose ("double array alignment padding not initialized to nul\n");
1196             return FALSE;
1197           }
1198         
1199         *end_pos = align_8 + len * 8;
1200       }
1201       break;
1202       
1203     case DBUS_TYPE_STRING_ARRAY:
1204       {
1205         int len;
1206         int i;
1207         
1208         len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
1209         if (len < 0)
1210           return FALSE;
1211
1212         for (i = 0; i < len; i++)
1213           {
1214             int str_len;
1215             
1216             str_len = demarshal_and_validate_len (str, byte_order,
1217                                                   pos, &pos);
1218             if (str_len < 0)
1219               return FALSE;
1220
1221             if (!validate_string (str, pos, str_len, &pos))
1222               return FALSE;            
1223           }
1224
1225         *end_pos = pos;
1226       }
1227       break;
1228       
1229     default:
1230       _dbus_verbose ("Unknown message arg type %d\n", *data);
1231       return FALSE;
1232     }
1233
1234   if (*end_pos > _dbus_string_get_length (str))
1235     return FALSE;
1236   
1237   return TRUE;
1238 }
1239
1240
1241 /**
1242  * If in verbose mode, print a block of binary data.
1243  *
1244  * @todo right now it prints even if not in verbose mode
1245  * 
1246  * @param data the data
1247  * @param len the length of the data
1248  */
1249 void
1250 _dbus_verbose_bytes (const unsigned char *data,
1251                      int                  len)
1252 {
1253   int i;
1254   const unsigned char *aligned;
1255
1256   _dbus_assert (len >= 0);
1257   
1258   /* Print blanks on first row if appropriate */
1259   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
1260   if (aligned > data)
1261     aligned -= 4;
1262   _dbus_assert (aligned <= data);
1263
1264   if (aligned != data)
1265     {
1266       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 
1267       while (aligned != data)
1268         {
1269           _dbus_verbose ("    ");
1270           ++aligned;
1271         }
1272     }
1273
1274   /* now print the bytes */
1275   i = 0;
1276   while (i < len)
1277     {
1278       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1279         {
1280           _dbus_verbose ("%4d\t%p: ",
1281                    i, &data[i]);
1282         }
1283       
1284       if (data[i] >= 32 &&
1285           data[i] <= 126)
1286         _dbus_verbose (" '%c' ", data[i]);
1287       else
1288         _dbus_verbose ("0x%s%x ",
1289                  data[i] <= 0xf ? "0" : "", data[i]);
1290
1291       ++i;
1292
1293       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1294         {
1295           if (i > 3)
1296             _dbus_verbose ("BE: %d LE: %d",
1297                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
1298                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
1299
1300           if (i > 7 && 
1301               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
1302             {
1303               _dbus_verbose (" dbl: %g",
1304                              *(double*)&data[i-8]);
1305             }
1306           
1307           _dbus_verbose ("\n");
1308         }
1309     }
1310
1311   _dbus_verbose ("\n");
1312 }
1313
1314 /**
1315  * Dump the given part of the string to verbose log.
1316  *
1317  * @param str the string
1318  * @param start the start of range to dump
1319  * @param len length of range
1320  */
1321 void
1322 _dbus_verbose_bytes_of_string (const DBusString    *str,
1323                                int                  start,
1324                                int                  len)
1325 {
1326   const char *d;
1327   int real_len;
1328
1329   real_len = _dbus_string_get_length (str);
1330
1331   _dbus_assert (start >= 0);
1332   
1333   if (start > real_len)
1334     {
1335       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
1336                      start, len, real_len);
1337       return;
1338     }
1339
1340   if ((start + len) > real_len)
1341     {
1342       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
1343                      start, len, real_len);
1344       len = real_len - start;
1345     }
1346   
1347   
1348   _dbus_string_get_const_data_len (str, &d, start, len);
1349
1350   _dbus_verbose_bytes (d, len);
1351 }
1352
1353 /** @} */
1354
1355 #ifdef DBUS_BUILD_TESTS
1356 #include "dbus-test.h"
1357 #include <stdio.h>
1358
1359 dbus_bool_t
1360 _dbus_marshal_test (void)
1361 {
1362   DBusString str;
1363   char *tmp1, *tmp2;
1364   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
1365   int pos = 0, len;
1366   
1367   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1368     _dbus_assert_not_reached ("failed to init string");
1369
1370   /* Marshal doubles */
1371   if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
1372     _dbus_assert_not_reached ("could not marshal double value");
1373   _dbus_assert (_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14);
1374
1375   if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
1376     _dbus_assert_not_reached ("could not marshal double value");
1377   _dbus_assert (_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14);
1378   
1379   /* Marshal signed integers */
1380   if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
1381     _dbus_assert_not_reached ("could not marshal signed integer value");
1382   _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678);
1383
1384   if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
1385     _dbus_assert_not_reached ("could not marshal signed integer value");
1386   _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678);
1387   
1388   /* Marshal unsigned integers */
1389   if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
1390     _dbus_assert_not_reached ("could not marshal signed integer value");
1391   _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678);
1392   
1393   if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
1394     _dbus_assert_not_reached ("could not marshal signed integer value");
1395   _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678);
1396
1397   /* Marshal strings */
1398   tmp1 = "This is the dbus test string";
1399   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
1400     _dbus_assert_not_reached ("could not marshal string");
1401   tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
1402   _dbus_assert (strcmp (tmp1, tmp2) == 0);
1403   dbus_free (tmp2);
1404
1405   tmp1 = "This is the dbus test string";
1406   if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
1407     _dbus_assert_not_reached ("could not marshal string");
1408   tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
1409   _dbus_assert (strcmp (tmp1, tmp2) == 0);
1410   dbus_free (tmp2);
1411
1412   /* Marshal signed integer arrays */
1413   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
1414     _dbus_assert_not_reached ("could not marshal integer array");
1415   array2 = _dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &len);
1416
1417   if (len != 3)
1418     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
1419   dbus_free (array2);
1420   
1421
1422
1423   _dbus_string_free (&str);
1424   
1425       
1426   return TRUE;
1427 }
1428
1429 #endif /* DBUS_BUILD_TESTS */