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