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