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