2003-02-26 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  *
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_BOOLEAN:
883       *end_pos = pos + 2;
884       break;
885       
886     case DBUS_TYPE_INT32:
887       *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
888
889       break;
890
891     case DBUS_TYPE_UINT32:
892       *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
893
894       break;
895
896     case DBUS_TYPE_DOUBLE:
897       *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (double)) + sizeof (double);
898
899       break;
900
901     case DBUS_TYPE_STRING:
902       {
903         int len;
904
905         /* Demarshal the length */
906         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
907
908         *end_pos = pos + len + 1;
909       }
910       break;
911
912     case DBUS_TYPE_BOOLEAN_ARRAY:
913     case DBUS_TYPE_BYTE_ARRAY:
914       {
915         int len;
916
917         /* Demarshal the length */
918         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
919         
920         *end_pos = pos + len;
921       }
922       break;
923
924     case DBUS_TYPE_INT32_ARRAY:
925       {
926         int len, new_pos;
927
928         /* Demarshal the length */
929         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
930         
931         *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_int32_t))
932           + (len * sizeof (dbus_int32_t));
933       }
934       break;
935
936     case DBUS_TYPE_UINT32_ARRAY:
937       {
938         int len, new_pos;
939
940         /* Demarshal the length */
941         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
942
943         *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_uint32_t))
944           + (len * sizeof (dbus_uint32_t));
945       }
946       break;
947
948     case DBUS_TYPE_DOUBLE_ARRAY:
949       {
950         int len, new_pos;
951         
952         /* Demarshal the length */
953         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
954
955         *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (double))
956           + (len * sizeof (double));
957       }
958       break;
959       
960     case DBUS_TYPE_STRING_ARRAY:
961       {
962         int len, i;
963         
964         /* Demarshal the length */
965         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
966
967         for (i = 0; i < len; i++)
968           {
969             int str_len;
970             
971             /* Demarshal string length */
972             str_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
973             pos += str_len + 1;
974           }
975
976         *end_pos = pos;
977       }
978       break;
979       
980     default:
981       _dbus_warn ("Unknown message arg type %d\n", *data);
982       _dbus_assert_not_reached ("Unknown message argument type\n");
983       return FALSE;
984     }
985
986   if (*end_pos > _dbus_string_get_length (str))
987     return FALSE;
988   
989   return TRUE;
990 }
991
992 /**
993  * Demarshals and validates a length; returns < 0 if the validation
994  * fails. The length is required to be small enough that
995  * len*sizeof(double) will not overflow, and small enough to fit in a
996  * signed integer.
997  *
998  * @param str the string
999  * @param byte_order the byte order
1000  * @param pos the unaligned string position (snap to next aligned)
1001  * @param new_pos return location for new position.
1002  */
1003 static int
1004 demarshal_and_validate_len (const DBusString *str,
1005                             int               byte_order,
1006                             int               pos,
1007                             int              *new_pos)
1008 {
1009   int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1010   unsigned int len;
1011   
1012   if ((align_4 + 4) >= _dbus_string_get_length (str))
1013     {
1014       _dbus_verbose ("not enough room in message for array length\n");
1015       return -1;
1016     }
1017   
1018   if (!_dbus_string_validate_nul (str, pos,
1019                                   align_4 - pos))
1020     {
1021       _dbus_verbose ("array length alignment padding not initialized to nul\n");
1022       return -1;
1023     }
1024
1025   len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
1026
1027   /* note that the len may be a number of doubles, so we need it to be
1028    * at least SIZE_T_MAX / 8, but make it smaller just to keep things
1029    * sane.  We end up using ints for most sizes to avoid unsigned mess
1030    * so limit to maximum 32-bit signed int divided by at least 8, more
1031    * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
1032    */  
1033 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
1034   if (len > MAX_ARRAY_LENGTH)
1035     {
1036       _dbus_verbose ("array length %u exceeds maximum of %u\n",
1037                      len, MAX_ARRAY_LENGTH);
1038       return -1;
1039     }
1040   else
1041     return (int) len;
1042 }
1043
1044 static dbus_bool_t
1045 validate_string (const DBusString *str,
1046                  int               pos,
1047                  int               len_without_nul,
1048                  int              *end_pos)
1049 {
1050   *end_pos = pos + len_without_nul + 1;
1051   
1052   if (*end_pos > _dbus_string_get_length (str))
1053     {
1054       _dbus_verbose ("string length outside length of the message\n");
1055       return FALSE;
1056     }
1057   
1058   if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
1059     {
1060       _dbus_verbose ("string arg not nul-terminated\n");
1061       return FALSE;
1062     }
1063   
1064   if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
1065     {
1066       _dbus_verbose ("string is not valid UTF-8\n");
1067       return FALSE;
1068     }
1069
1070   return TRUE;
1071 }   
1072
1073 /** 
1074  * Validates an argument, checking that it is well-formed, for example
1075  * no ludicrous length fields, strings are nul-terminated, etc.
1076  * Returns the end position of the argument in end_pos, and
1077  * returns #TRUE if a valid arg begins at "pos"
1078  *
1079  * @todo security: need to audit this function.
1080  * 
1081  * @param str a string
1082  * @param byte_order the byte order to use
1083  * @param pos the pos where the arg starts (offset of its typecode)
1084  * @param end_pos pointer where the position right
1085  * after the end position will follow
1086  * @returns #TRUE if the arg is valid.
1087  */
1088 dbus_bool_t
1089 _dbus_marshal_validate_arg (const DBusString *str,
1090                             int               byte_order,
1091                             int               pos,
1092                             int              *end_pos)
1093 {
1094   const char *data;
1095
1096   if (pos >= _dbus_string_get_length (str))
1097     return FALSE;
1098
1099   _dbus_string_get_const_data_len (str, &data, pos, 1);
1100   
1101   switch (*data)
1102     {
1103     case DBUS_TYPE_INVALID:
1104       return FALSE;
1105       break;
1106
1107     case DBUS_TYPE_NIL:
1108       *end_pos = pos + 1;
1109       break;
1110
1111     case DBUS_TYPE_BOOLEAN:
1112       {
1113         unsigned char c;
1114
1115         c = _dbus_string_get_byte (str, pos + 1);
1116
1117         if (c != 0 && c != 1)
1118           {
1119             _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
1120             return FALSE;
1121           }
1122         
1123       *end_pos = pos + 2;
1124       break;
1125       }
1126     case DBUS_TYPE_INT32:
1127     case DBUS_TYPE_UINT32:
1128       {
1129         int align_4 = _DBUS_ALIGN_VALUE (pos + 1, 4);
1130         
1131         if (!_dbus_string_validate_nul (str, pos + 1,
1132                                         align_4 - pos - 1))
1133           {
1134             _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
1135             return FALSE;
1136           }
1137
1138         *end_pos = align_4 + 4;
1139       }
1140       break;
1141
1142     case DBUS_TYPE_DOUBLE:
1143       {
1144         int align_8 = _DBUS_ALIGN_VALUE (pos + 1, 8);
1145
1146         _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
1147         
1148         if (!_dbus_string_validate_nul (str, pos + 1,
1149                                         align_8 - pos - 1))
1150           {
1151             _dbus_verbose ("double alignment padding not initialized to nul\n");
1152             return FALSE;
1153           }
1154
1155         *end_pos = align_8 + 8;
1156       }
1157       break;
1158
1159     case DBUS_TYPE_STRING:
1160       {
1161         int len;
1162
1163         /* Demarshal the length, which does NOT include
1164          * nul termination
1165          */
1166         len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
1167         if (len < 0)
1168           return FALSE;
1169
1170         if (!validate_string (str, pos, len, end_pos))
1171           return FALSE;
1172       }
1173       break;
1174
1175     case DBUS_TYPE_BOOLEAN_ARRAY:
1176       {
1177         int len, i;
1178
1179         len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
1180         if (len < 0)
1181           return FALSE;
1182
1183         i = 0;
1184         while (i < len)
1185           {
1186             unsigned char c = _dbus_string_get_byte (str, pos + i);
1187
1188             if (c != 0 && c != 1)
1189               {
1190                 _dbus_verbose ("boolean value must be either 0 or 1, not %d (pos %d)\n", c, pos);
1191                 return FALSE;
1192               }
1193
1194             i++;
1195           }
1196         *end_pos = pos + len;
1197         break;
1198       }
1199     case DBUS_TYPE_BYTE_ARRAY:
1200       {
1201         int len;
1202
1203         len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
1204         if (len < 0)
1205           return FALSE;
1206         
1207         *end_pos = pos + len;
1208       }
1209       break;
1210
1211     case DBUS_TYPE_INT32_ARRAY:
1212     case DBUS_TYPE_UINT32_ARRAY:
1213       {
1214         int len;
1215
1216         len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
1217         if (len < 0)
1218           return FALSE;
1219
1220         _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned int) pos);
1221         
1222         *end_pos = pos + len * 4;
1223       }
1224       break;
1225
1226     case DBUS_TYPE_DOUBLE_ARRAY:
1227       {
1228         int len;
1229         int align_8;
1230
1231         len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
1232         if (len < 0)
1233           return FALSE;
1234
1235         align_8 = _DBUS_ALIGN_VALUE (pos, 8);
1236         if (!_dbus_string_validate_nul (str, pos,
1237                                         align_8 - pos))
1238           {
1239             _dbus_verbose ("double array alignment padding not initialized to nul\n");
1240             return FALSE;
1241           }
1242         
1243         *end_pos = align_8 + len * 8;
1244       }
1245       break;
1246       
1247     case DBUS_TYPE_STRING_ARRAY:
1248       {
1249         int len;
1250         int i;
1251         
1252         len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
1253         if (len < 0)
1254           return FALSE;
1255
1256         for (i = 0; i < len; i++)
1257           {
1258             int str_len;
1259             
1260             str_len = demarshal_and_validate_len (str, byte_order,
1261                                                   pos, &pos);
1262             if (str_len < 0)
1263               return FALSE;
1264
1265             if (!validate_string (str, pos, str_len, &pos))
1266               return FALSE;            
1267           }
1268
1269         *end_pos = pos;
1270       }
1271       break;
1272       
1273     default:
1274       _dbus_verbose ("Unknown message arg type %d\n", *data);
1275       return FALSE;
1276     }
1277
1278   if (*end_pos > _dbus_string_get_length (str))
1279     return FALSE;
1280   
1281   return TRUE;
1282 }
1283
1284
1285 /**
1286  * If in verbose mode, print a block of binary data.
1287  *
1288  * @todo right now it prints even if not in verbose mode
1289  * 
1290  * @param data the data
1291  * @param len the length of the data
1292  */
1293 void
1294 _dbus_verbose_bytes (const unsigned char *data,
1295                      int                  len)
1296 {
1297   int i;
1298   const unsigned char *aligned;
1299
1300   _dbus_assert (len >= 0);
1301   
1302   /* Print blanks on first row if appropriate */
1303   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
1304   if (aligned > data)
1305     aligned -= 4;
1306   _dbus_assert (aligned <= data);
1307
1308   if (aligned != data)
1309     {
1310       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 
1311       while (aligned != data)
1312         {
1313           _dbus_verbose ("    ");
1314           ++aligned;
1315         }
1316     }
1317
1318   /* now print the bytes */
1319   i = 0;
1320   while (i < len)
1321     {
1322       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1323         {
1324           _dbus_verbose ("%4d\t%p: ",
1325                    i, &data[i]);
1326         }
1327       
1328       if (data[i] >= 32 &&
1329           data[i] <= 126)
1330         _dbus_verbose (" '%c' ", data[i]);
1331       else
1332         _dbus_verbose ("0x%s%x ",
1333                  data[i] <= 0xf ? "0" : "", data[i]);
1334
1335       ++i;
1336
1337       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1338         {
1339           if (i > 3)
1340             _dbus_verbose ("BE: %d LE: %d",
1341                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
1342                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
1343
1344           if (i > 7 && 
1345               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
1346             {
1347               _dbus_verbose (" dbl: %g",
1348                              *(double*)&data[i-8]);
1349             }
1350           
1351           _dbus_verbose ("\n");
1352         }
1353     }
1354
1355   _dbus_verbose ("\n");
1356 }
1357
1358 /**
1359  * Dump the given part of the string to verbose log.
1360  *
1361  * @param str the string
1362  * @param start the start of range to dump
1363  * @param len length of range
1364  */
1365 void
1366 _dbus_verbose_bytes_of_string (const DBusString    *str,
1367                                int                  start,
1368                                int                  len)
1369 {
1370   const char *d;
1371   int real_len;
1372
1373   real_len = _dbus_string_get_length (str);
1374
1375   _dbus_assert (start >= 0);
1376   
1377   if (start > real_len)
1378     {
1379       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
1380                      start, len, real_len);
1381       return;
1382     }
1383
1384   if ((start + len) > real_len)
1385     {
1386       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
1387                      start, len, real_len);
1388       len = real_len - start;
1389     }
1390   
1391   
1392   _dbus_string_get_const_data_len (str, &d, start, len);
1393
1394   _dbus_verbose_bytes (d, len);
1395 }
1396
1397 /** @} */
1398
1399 #ifdef DBUS_BUILD_TESTS
1400 #include "dbus-test.h"
1401 #include <stdio.h>
1402
1403 dbus_bool_t
1404 _dbus_marshal_test (void)
1405 {
1406   DBusString str;
1407   char *tmp1, *tmp2;
1408   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
1409   int pos = 0, len;
1410   
1411   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
1412     _dbus_assert_not_reached ("failed to init string");
1413
1414   /* Marshal doubles */
1415   if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
1416     _dbus_assert_not_reached ("could not marshal double value");
1417   if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
1418     _dbus_assert_not_reached ("demarshal failed");
1419
1420   if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
1421     _dbus_assert_not_reached ("could not marshal double value");
1422   if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
1423     _dbus_assert_not_reached ("demarshal failed");
1424   
1425   /* Marshal signed integers */
1426   if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
1427     _dbus_assert_not_reached ("could not marshal signed integer value");
1428   if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
1429     _dbus_assert_not_reached ("demarshal failed");
1430
1431   if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
1432     _dbus_assert_not_reached ("could not marshal signed integer value");
1433   if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
1434     _dbus_assert_not_reached ("demarshal failed");
1435   
1436   /* Marshal unsigned integers */
1437   if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
1438     _dbus_assert_not_reached ("could not marshal signed integer value");
1439   if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
1440     _dbus_assert_not_reached ("demarshal failed");
1441   
1442   if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
1443     _dbus_assert_not_reached ("could not marshal signed integer value");
1444   if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
1445     _dbus_assert_not_reached ("demarshal failed");
1446
1447   /* Marshal strings */
1448   tmp1 = "This is the dbus test string";
1449   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
1450     _dbus_assert_not_reached ("could not marshal string");
1451   tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
1452   if (!strcmp (tmp1, tmp2) == 0)
1453     _dbus_assert_not_reached ("demarshal failed");
1454   dbus_free (tmp2);
1455
1456   tmp1 = "This is the dbus test string";
1457   if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
1458     _dbus_assert_not_reached ("could not marshal string");
1459   tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
1460   if (!strcmp (tmp1, tmp2) == 0)
1461     _dbus_assert_not_reached ("demarshal failed");
1462   dbus_free (tmp2);
1463
1464   /* Marshal signed integer arrays */
1465   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
1466     _dbus_assert_not_reached ("could not marshal integer array");
1467   array2 = _dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &len);
1468
1469   if (len != 3)
1470     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
1471   dbus_free (array2);
1472   
1473
1474
1475   _dbus_string_free (&str);
1476   
1477       
1478   return TRUE;
1479 }
1480
1481 #endif /* DBUS_BUILD_TESTS */