• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-marshal-basic.c  Marshalling routines for basic (primitive) types
3  *
4  * Copyright (C) 2002 CodeFactory AB
5  * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
6  *
7  * Licensed under the Academic Free License version 2.1
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24 
25 #include <config.h>
26 #include "dbus-internals.h"
27 #include "dbus-marshal-basic.h"
28 #include "dbus-signature.h"
29 
30 #include <string.h>
31 
32 #if defined(__GNUC__) && (__GNUC__ >= 4)
33 # define _DBUS_ASSERT_ALIGNMENT(type, op, val) \
34   _DBUS_STATIC_ASSERT (__extension__ __alignof__ (type) op val)
35 #else
36   /* not gcc, so probably no alignof operator: just use a no-op statement
37    * that's valid in the same contexts */
38 # define _DBUS_ASSERT_ALIGNMENT(type, op, val) \
39   _DBUS_STATIC_ASSERT (TRUE)
40 #endif
41 
42 /* True by definition, but just for completeness... */
43 _DBUS_STATIC_ASSERT (sizeof (char) == 1);
44 _DBUS_ASSERT_ALIGNMENT (char, ==, 1);
45 
46 _DBUS_STATIC_ASSERT (sizeof (dbus_int16_t) == 2);
47 _DBUS_ASSERT_ALIGNMENT (dbus_int16_t, <=, 2);
48 _DBUS_STATIC_ASSERT (sizeof (dbus_uint16_t) == 2);
49 _DBUS_ASSERT_ALIGNMENT (dbus_uint16_t, <=, 2);
50 
51 _DBUS_STATIC_ASSERT (sizeof (dbus_int32_t) == 4);
52 _DBUS_ASSERT_ALIGNMENT (dbus_int32_t, <=, 4);
53 _DBUS_STATIC_ASSERT (sizeof (dbus_uint32_t) == 4);
54 _DBUS_ASSERT_ALIGNMENT (dbus_uint32_t, <=, 4);
55 _DBUS_STATIC_ASSERT (sizeof (dbus_bool_t) == 4);
56 _DBUS_ASSERT_ALIGNMENT (dbus_bool_t, <=, 4);
57 
58 _DBUS_STATIC_ASSERT (sizeof (double) == 8);
59 _DBUS_ASSERT_ALIGNMENT (double, <=, 8);
60 
61 #ifdef DBUS_HAVE_INT64
62 _DBUS_STATIC_ASSERT (sizeof (dbus_int64_t) == 8);
63 _DBUS_ASSERT_ALIGNMENT (dbus_int64_t, <=, 8);
64 _DBUS_STATIC_ASSERT (sizeof (dbus_uint64_t) == 8);
65 _DBUS_ASSERT_ALIGNMENT (dbus_uint64_t, <=, 8);
66 #endif
67 
68 _DBUS_STATIC_ASSERT (sizeof (DBusBasicValue) >= 8);
69 /* The alignment of a DBusBasicValue might conceivably be > 8 because of the
70  * pointer, so we don't assert about it */
71 
72 _DBUS_STATIC_ASSERT (sizeof (DBus8ByteStruct) == 8);
73 _DBUS_ASSERT_ALIGNMENT (DBus8ByteStruct, <=, 8);
74 
75 /**
76  * @defgroup DBusMarshal marshaling and unmarshaling
77  * @ingroup  DBusInternals
78  * @brief functions to marshal/unmarshal data from the wire
79  *
80  * Types and functions related to converting primitive data types from
81  * wire format to native machine format, and vice versa.
82  *
83  * A signature is just a string with multiple types one after the other.
84  * for example a type is "i" or "(ii)", a signature is "i(ii)"
85  * where i is int and (ii) is struct { int; int; }
86  *
87  * @{
88  */
89 
90 static void
pack_2_octets(dbus_uint16_t value,int byte_order,unsigned char * data)91 pack_2_octets (dbus_uint16_t   value,
92                int             byte_order,
93                unsigned char  *data)
94 {
95   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
96 
97   if ((byte_order) == DBUS_LITTLE_ENDIAN)
98     *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_LE (value);
99   else
100     *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_BE (value);
101 }
102 
103 static void
pack_4_octets(dbus_uint32_t value,int byte_order,unsigned char * data)104 pack_4_octets (dbus_uint32_t   value,
105                int             byte_order,
106                unsigned char  *data)
107 {
108   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
109 
110   if ((byte_order) == DBUS_LITTLE_ENDIAN)
111     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
112   else
113     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
114 }
115 
116 static void
pack_8_octets(DBusBasicValue value,int byte_order,unsigned char * data)117 pack_8_octets (DBusBasicValue     value,
118                int                byte_order,
119                unsigned char     *data)
120 {
121   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
122 
123 #ifdef DBUS_HAVE_INT64
124   if ((byte_order) == DBUS_LITTLE_ENDIAN)
125     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u64);
126   else
127     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u64);
128 #else
129   *(DBus8ByteStruct*)data = value.eight;
130   swap_8_octets ((DBusBasicValue*)data, byte_order);
131 #endif
132 }
133 
134 /**
135  * Packs a 32 bit unsigned integer into a data pointer.
136  *
137  * @param value the value
138  * @param byte_order the byte order to use
139  * @param data the data pointer
140  */
141 void
_dbus_pack_uint32(dbus_uint32_t value,int byte_order,unsigned char * data)142 _dbus_pack_uint32 (dbus_uint32_t   value,
143                    int             byte_order,
144                    unsigned char  *data)
145 {
146   pack_4_octets (value, byte_order, data);
147 }
148 
149 #ifndef DBUS_HAVE_INT64
150 /* from ORBit */
151 static void
swap_bytes(unsigned char * data,unsigned int len)152 swap_bytes (unsigned char *data,
153             unsigned int   len)
154 {
155   unsigned char *p1 = data;
156   unsigned char *p2 = data + len - 1;
157 
158   while (p1 < p2)
159     {
160       unsigned char tmp = *p1;
161       *p1 = *p2;
162       *p2 = tmp;
163 
164       --p2;
165       ++p1;
166     }
167 }
168 #endif /* !DBUS_HAVE_INT64 */
169 
170 static void
swap_8_octets(DBusBasicValue * value,int byte_order)171 swap_8_octets (DBusBasicValue    *value,
172                int                byte_order)
173 {
174   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
175     {
176 #ifdef DBUS_HAVE_INT64
177       value->u64 = DBUS_UINT64_SWAP_LE_BE (value->u64);
178 #else
179       swap_bytes (&value->bytes, 8);
180 #endif
181     }
182 }
183 
184 #if 0
185 static DBusBasicValue
186 unpack_8_octets (int                  byte_order,
187                  const unsigned char *data)
188 {
189   DBusBasicValue r;
190 
191   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
192   _dbus_assert (sizeof (r) == 8);
193 
194 #ifdef DBUS_HAVE_INT64
195   if (byte_order == DBUS_LITTLE_ENDIAN)
196     r.u64 = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
197   else
198     r.u64 = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
199 #else
200   r.eight = *(DBus8ByteStruct*)data;
201   swap_8_octets (&r, byte_order);
202 #endif
203 
204   return r;
205 }
206 #endif
207 
208 #ifndef _dbus_unpack_uint16
209 /**
210  * Unpacks a 16 bit unsigned integer from a data pointer
211  *
212  * @param byte_order The byte order to use
213  * @param data the data pointer
214  * @returns the integer
215  */
216 dbus_uint16_t
_dbus_unpack_uint16(int byte_order,const unsigned char * data)217 _dbus_unpack_uint16 (int                  byte_order,
218                      const unsigned char *data)
219 {
220   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
221 
222   if (byte_order == DBUS_LITTLE_ENDIAN)
223     return DBUS_UINT16_FROM_LE (*(dbus_uint16_t*)data);
224   else
225     return DBUS_UINT16_FROM_BE (*(dbus_uint16_t*)data);
226 }
227 #endif /* _dbus_unpack_uint16 */
228 
229 #ifndef _dbus_unpack_uint32
230 /**
231  * Unpacks a 32 bit unsigned integer from a data pointer
232  *
233  * @param byte_order The byte order to use
234  * @param data the data pointer
235  * @returns the integer
236  */
237 dbus_uint32_t
_dbus_unpack_uint32(int byte_order,const unsigned char * data)238 _dbus_unpack_uint32 (int                  byte_order,
239                      const unsigned char *data)
240 {
241   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
242 
243   if (byte_order == DBUS_LITTLE_ENDIAN)
244     return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
245   else
246     return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
247 }
248 #endif /* _dbus_unpack_uint32 */
249 
250 static void
set_2_octets(DBusString * str,int offset,dbus_uint16_t value,int byte_order)251 set_2_octets (DBusString          *str,
252               int                  offset,
253               dbus_uint16_t        value,
254               int                  byte_order)
255 {
256   char *data;
257 
258   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
259                 byte_order == DBUS_BIG_ENDIAN);
260 
261   data = _dbus_string_get_data_len (str, offset, 2);
262 
263   pack_2_octets (value, byte_order, data);
264 }
265 
266 static void
set_4_octets(DBusString * str,int offset,dbus_uint32_t value,int byte_order)267 set_4_octets (DBusString          *str,
268               int                  offset,
269               dbus_uint32_t        value,
270               int                  byte_order)
271 {
272   char *data;
273 
274   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
275                 byte_order == DBUS_BIG_ENDIAN);
276 
277   data = _dbus_string_get_data_len (str, offset, 4);
278 
279   pack_4_octets (value, byte_order, data);
280 }
281 
282 static void
set_8_octets(DBusString * str,int offset,DBusBasicValue value,int byte_order)283 set_8_octets (DBusString          *str,
284               int                  offset,
285               DBusBasicValue       value,
286               int                  byte_order)
287 {
288   char *data;
289 
290   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
291                 byte_order == DBUS_BIG_ENDIAN);
292 
293   data = _dbus_string_get_data_len (str, offset, 8);
294 
295   pack_8_octets (value, byte_order, data);
296 }
297 
298 /**
299  * Sets the 4 bytes at the given offset to a marshaled unsigned
300  * integer, replacing anything found there previously.
301  *
302  * @param str the string to write the marshalled int to
303  * @param pos the byte offset where int should be written
304  * @param value the value
305  * @param byte_order the byte order to use
306  *
307  */
308 void
_dbus_marshal_set_uint32(DBusString * str,int pos,dbus_uint32_t value,int byte_order)309 _dbus_marshal_set_uint32 (DBusString          *str,
310                           int                  pos,
311                           dbus_uint32_t        value,
312                           int                  byte_order)
313 {
314   set_4_octets (str, pos, value, byte_order);
315 }
316 
317 /**
318  * Sets the existing marshaled string at the given offset with
319  * a new marshaled string. The given offset must point to
320  * an existing string or the wrong length will be deleted
321  * and replaced with the new string.
322  *
323  * Note: no attempt is made by this function to re-align
324  * any data which has been already marshalled after this
325  * string. Use with caution.
326  *
327  * @param str the string to write the marshalled string to
328  * @param pos the position of the marshaled string length
329  * @param value the value
330  * @param byte_order the byte order to use
331  * @param old_end_pos place to store byte after the nul byte of the old value
332  * @param new_end_pos place to store byte after the nul byte of the new value
333  * @returns #TRUE on success, #FALSE if no memory
334  *
335  */
336 static dbus_bool_t
set_string(DBusString * str,int pos,const char * value,int byte_order,int * old_end_pos,int * new_end_pos)337 set_string (DBusString          *str,
338             int                  pos,
339             const char          *value,
340             int                  byte_order,
341             int                 *old_end_pos,
342             int                 *new_end_pos)
343 {
344   int old_len, new_len;
345   DBusString dstr;
346 
347   _dbus_string_init_const (&dstr, value);
348 
349   _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned) pos);
350   old_len = _dbus_unpack_uint32 (byte_order,
351                                  _dbus_string_get_const_data_len (str, pos, 4));
352 
353   new_len = _dbus_string_get_length (&dstr);
354 
355   if (!_dbus_string_replace_len (&dstr, 0, new_len,
356                                  str, pos + 4, old_len))
357     return FALSE;
358 
359   _dbus_marshal_set_uint32 (str, pos, new_len, byte_order);
360 
361   if (old_end_pos)
362     *old_end_pos = pos + 4 + old_len + 1;
363   if (new_end_pos)
364     *new_end_pos = pos + 4 + new_len + 1;
365 
366   return TRUE;
367 }
368 
369 /**
370  * Sets the existing marshaled signature at the given offset to a new
371  * marshaled signature. Same basic ideas as set_string().
372  *
373  * @param str the string to write the marshalled signature to
374  * @param pos the position of the marshaled signature length
375  * @param value the value
376  * @param byte_order the byte order to use
377  * @param old_end_pos place to store byte after the nul byte of the old value
378  * @param new_end_pos place to store byte after the nul byte of the new value
379  * @returns #TRUE on success, #FALSE if no memory
380  *
381  */
382 static dbus_bool_t
set_signature(DBusString * str,int pos,const char * value,int byte_order,int * old_end_pos,int * new_end_pos)383 set_signature (DBusString          *str,
384                int                  pos,
385                const char          *value,
386                int                  byte_order,
387                int                 *old_end_pos,
388                int                 *new_end_pos)
389 {
390   int old_len, new_len;
391   DBusString dstr;
392 
393   _dbus_string_init_const (&dstr, value);
394 
395   old_len = _dbus_string_get_byte (str, pos);
396   new_len = _dbus_string_get_length (&dstr);
397 
398   if (!_dbus_string_replace_len (&dstr, 0, new_len,
399                                  str, pos + 1, old_len))
400     return FALSE;
401 
402   _dbus_string_set_byte (str, pos, new_len);
403 
404   if (old_end_pos)
405     *old_end_pos = pos + 1 + old_len + 1;
406   if (new_end_pos)
407     *new_end_pos = pos + 1 + new_len + 1;
408 
409   return TRUE;
410 }
411 
412 /**
413  * Sets an existing basic type value to a new value.
414  * Arguments work the same way as _dbus_marshal_basic_type().
415  *
416  * @param str the string
417  * @param pos location of the current value
418  * @param type the type of the current and new values
419  * @param value the address of the new value
420  * @param byte_order byte order for marshaling
421  * @param old_end_pos location to store end position of the old value, or #NULL
422  * @param new_end_pos location to store end position of the new value, or #NULL
423  * @returns #FALSE if no memory
424  */
425 dbus_bool_t
_dbus_marshal_set_basic(DBusString * str,int pos,int type,const void * value,int byte_order,int * old_end_pos,int * new_end_pos)426 _dbus_marshal_set_basic (DBusString       *str,
427                          int               pos,
428                          int               type,
429                          const void       *value,
430                          int               byte_order,
431                          int              *old_end_pos,
432                          int              *new_end_pos)
433 {
434   const DBusBasicValue *vp;
435 
436   vp = value;
437 
438   switch (type)
439     {
440     case DBUS_TYPE_BYTE:
441       _dbus_string_set_byte (str, pos, vp->byt);
442       if (old_end_pos)
443         *old_end_pos = pos + 1;
444       if (new_end_pos)
445         *new_end_pos = pos + 1;
446       return TRUE;
447       break;
448     case DBUS_TYPE_INT16:
449     case DBUS_TYPE_UINT16:
450       pos = _DBUS_ALIGN_VALUE (pos, 2);
451       set_2_octets (str, pos, vp->u16, byte_order);
452       if (old_end_pos)
453         *old_end_pos = pos + 2;
454       if (new_end_pos)
455         *new_end_pos = pos + 2;
456       return TRUE;
457       break;
458     case DBUS_TYPE_BOOLEAN:
459     case DBUS_TYPE_INT32:
460     case DBUS_TYPE_UINT32:
461     case DBUS_TYPE_UNIX_FD:
462       pos = _DBUS_ALIGN_VALUE (pos, 4);
463       set_4_octets (str, pos, vp->u32, byte_order);
464       if (old_end_pos)
465         *old_end_pos = pos + 4;
466       if (new_end_pos)
467         *new_end_pos = pos + 4;
468       return TRUE;
469       break;
470     case DBUS_TYPE_INT64:
471     case DBUS_TYPE_UINT64:
472     case DBUS_TYPE_DOUBLE:
473       pos = _DBUS_ALIGN_VALUE (pos, 8);
474       set_8_octets (str, pos, *vp, byte_order);
475       if (old_end_pos)
476         *old_end_pos = pos + 8;
477       if (new_end_pos)
478         *new_end_pos = pos + 8;
479       return TRUE;
480       break;
481     case DBUS_TYPE_STRING:
482     case DBUS_TYPE_OBJECT_PATH:
483       pos = _DBUS_ALIGN_VALUE (pos, 4);
484       _dbus_assert (vp->str != NULL);
485       return set_string (str, pos, vp->str, byte_order,
486                          old_end_pos, new_end_pos);
487       break;
488     case DBUS_TYPE_SIGNATURE:
489       _dbus_assert (vp->str != NULL);
490       return set_signature (str, pos, vp->str, byte_order,
491                             old_end_pos, new_end_pos);
492       break;
493     default:
494       _dbus_assert_not_reached ("not a basic type");
495       return FALSE;
496       break;
497     }
498 }
499 
500 /**
501  * Convenience function to demarshal a 32 bit unsigned integer.
502  *
503  * @param str the string containing the data
504  * @param byte_order the byte order
505  * @param pos the position in the string
506  * @param new_pos the new position of the string
507  * @returns the demarshaled integer.
508  */
509 dbus_uint32_t
_dbus_marshal_read_uint32(const DBusString * str,int pos,int byte_order,int * new_pos)510 _dbus_marshal_read_uint32  (const DBusString *str,
511                             int               pos,
512                             int               byte_order,
513                             int              *new_pos)
514 {
515   pos = _DBUS_ALIGN_VALUE (pos, 4);
516 
517   if (new_pos)
518     *new_pos = pos + 4;
519 
520   _dbus_assert (pos + 4 <= _dbus_string_get_length (str));
521 
522   return _dbus_unpack_uint32 (byte_order,
523                               _dbus_string_get_const_data (str) + pos);
524 }
525 
526 /**
527  * Demarshals a basic-typed value. The "value" pointer is always
528  * the address of a variable of the basic type. So e.g.
529  * if the basic type is "double" then the pointer is
530  * a double*, and if it's "char*" then the pointer is
531  * a "char**".
532  *
533  * A value of type #DBusBasicValue is guaranteed to be large enough to
534  * hold any of the types that may be returned, which is handy if you
535  * are trying to do things generically. For example you can pass
536  * a DBusBasicValue* in to this function, and then pass the same
537  * DBusBasicValue* in to _dbus_marshal_basic_type() in order to
538  * move a value from one place to another.
539  *
540  * @param str the string containing the data
541  * @param pos position in the string
542  * @param type type of value to demarshal
543  * @param value pointer to return value data
544  * @param byte_order the byte order
545  * @param new_pos pointer to update with new position, or #NULL
546  **/
547 void
_dbus_marshal_read_basic(const DBusString * str,int pos,int type,void * value,int byte_order,int * new_pos)548 _dbus_marshal_read_basic (const DBusString      *str,
549                           int                    pos,
550                           int                    type,
551                           void                  *value,
552                           int                    byte_order,
553                           int                   *new_pos)
554 {
555   const char *str_data;
556 
557   _dbus_assert (dbus_type_is_basic (type));
558 
559   str_data = _dbus_string_get_const_data (str);
560 
561   /* Below we volatile types to avoid aliasing issues;
562    * see http://bugs.freedesktop.org/show_bug.cgi?id=20137
563    */
564 
565   switch (type)
566     {
567     case DBUS_TYPE_BYTE:
568       {
569       volatile unsigned char *vp = value;
570       *vp = (unsigned char) _dbus_string_get_byte (str, pos);
571       (pos)++;
572       }
573       break;
574     case DBUS_TYPE_INT16:
575     case DBUS_TYPE_UINT16:
576       {
577       volatile dbus_uint16_t *vp = value;
578       pos = _DBUS_ALIGN_VALUE (pos, 2);
579       *vp = *(dbus_uint16_t *)(str_data + pos);
580       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
581 	*vp = DBUS_UINT16_SWAP_LE_BE (*vp);
582       pos += 2;
583       }
584       break;
585     case DBUS_TYPE_INT32:
586     case DBUS_TYPE_UINT32:
587     case DBUS_TYPE_BOOLEAN:
588     case DBUS_TYPE_UNIX_FD:
589       {
590       volatile dbus_uint32_t *vp = value;
591       pos = _DBUS_ALIGN_VALUE (pos, 4);
592       *vp = *(dbus_uint32_t *)(str_data + pos);
593       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
594 	*vp = DBUS_UINT32_SWAP_LE_BE (*vp);
595       pos += 4;
596       }
597       break;
598     case DBUS_TYPE_INT64:
599     case DBUS_TYPE_UINT64:
600     case DBUS_TYPE_DOUBLE:
601       {
602       volatile dbus_uint64_t *vp = value;
603       pos = _DBUS_ALIGN_VALUE (pos, 8);
604 #ifdef DBUS_HAVE_INT64
605       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
606         *vp = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t*)(str_data + pos));
607       else
608         *vp = *(dbus_uint64_t*)(str_data + pos);
609 #else
610       *vp = *(DBus8ByteStruct*) (str_data + pos);
611       swap_8_octets (vp, byte_order);
612 #endif
613       pos += 8;
614       }
615       break;
616     case DBUS_TYPE_STRING:
617     case DBUS_TYPE_OBJECT_PATH:
618       {
619         int len;
620         volatile char **vp = value;
621 
622         len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
623 
624         *vp = (char*) str_data + pos;
625 
626         pos += len + 1; /* length plus nul */
627       }
628       break;
629     case DBUS_TYPE_SIGNATURE:
630       {
631         int len;
632         volatile char **vp = value;
633 
634         len = _dbus_string_get_byte (str, pos);
635         pos += 1;
636 
637         *vp = (char*) str_data + pos;
638 
639         pos += len + 1; /* length plus nul */
640       }
641       break;
642     default:
643       _dbus_warn_check_failed ("type %s %d not a basic type\n",
644                                _dbus_type_to_string (type), type);
645       _dbus_assert_not_reached ("not a basic type");
646       break;
647     }
648 
649   if (new_pos)
650     *new_pos = pos;
651 }
652 
653 static dbus_bool_t
marshal_2_octets(DBusString * str,int insert_at,dbus_uint16_t value,int byte_order,int * pos_after)654 marshal_2_octets (DBusString   *str,
655                   int           insert_at,
656                   dbus_uint16_t value,
657                   int           byte_order,
658                   int          *pos_after)
659 {
660   dbus_bool_t retval;
661   int orig_len;
662 
663   _dbus_assert (sizeof (value) == 2);
664 
665   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
666     value = DBUS_UINT16_SWAP_LE_BE (value);
667 
668   orig_len = _dbus_string_get_length (str);
669 
670   retval = _dbus_string_insert_2_aligned (str, insert_at,
671                                           (const unsigned char *)&value);
672 
673   if (pos_after)
674     {
675       *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
676       _dbus_assert (*pos_after <= _dbus_string_get_length (str));
677     }
678 
679   return retval;
680 }
681 
682 static dbus_bool_t
marshal_4_octets(DBusString * str,int insert_at,dbus_uint32_t value,int byte_order,int * pos_after)683 marshal_4_octets (DBusString   *str,
684                   int           insert_at,
685                   dbus_uint32_t value,
686                   int           byte_order,
687                   int          *pos_after)
688 {
689   dbus_bool_t retval;
690   int orig_len;
691 
692   _dbus_assert (sizeof (value) == 4);
693 
694   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
695     value = DBUS_UINT32_SWAP_LE_BE (value);
696 
697   orig_len = _dbus_string_get_length (str);
698 
699   retval = _dbus_string_insert_4_aligned (str, insert_at,
700                                           (const unsigned char *)&value);
701 
702   if (pos_after)
703     {
704       *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
705       _dbus_assert (*pos_after <= _dbus_string_get_length (str));
706     }
707 
708   return retval;
709 }
710 
711 static dbus_bool_t
marshal_8_octets(DBusString * str,int insert_at,DBusBasicValue value,int byte_order,int * pos_after)712 marshal_8_octets (DBusString    *str,
713                   int            insert_at,
714                   DBusBasicValue value,
715                   int            byte_order,
716                   int           *pos_after)
717 {
718   dbus_bool_t retval;
719   int orig_len;
720 
721   _dbus_assert (sizeof (value) == 8);
722 
723   swap_8_octets (&value, byte_order);
724 
725   orig_len = _dbus_string_get_length (str);
726 
727   retval = _dbus_string_insert_8_aligned (str, insert_at,
728                                           (const unsigned char *)&value);
729 
730   if (pos_after)
731     *pos_after = insert_at + _dbus_string_get_length (str) - orig_len;
732 
733   return retval;
734 }
735 
736 enum
737   {
738     MARSHAL_AS_STRING,
739     MARSHAL_AS_SIGNATURE,
740     MARSHAL_AS_BYTE_ARRAY
741   };
742 
743 static dbus_bool_t
marshal_len_followed_by_bytes(int marshal_as,DBusString * str,int insert_at,const unsigned char * value,int data_len,int byte_order,int * pos_after)744 marshal_len_followed_by_bytes (int                  marshal_as,
745                                DBusString          *str,
746                                int                  insert_at,
747                                const unsigned char *value,
748                                int                  data_len, /* doesn't include nul if any */
749                                int                  byte_order,
750                                int                 *pos_after)
751 {
752   int pos;
753   DBusString value_str;
754   int value_len;
755 
756   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN);
757   if (insert_at > _dbus_string_get_length (str))
758     _dbus_warn ("insert_at = %d string len = %d data_len = %d\n",
759                 insert_at, _dbus_string_get_length (str), data_len);
760 
761   if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
762     value_len = data_len;
763   else
764     value_len = data_len + 1; /* value has a nul */
765 
766   _dbus_string_init_const_len (&value_str, value, value_len);
767 
768   pos = insert_at;
769 
770   if (marshal_as == MARSHAL_AS_SIGNATURE)
771     {
772       _dbus_assert (data_len <= DBUS_MAXIMUM_SIGNATURE_LENGTH);
773       _dbus_assert (data_len <= 255); /* same as max sig len right now */
774 
775       if (!_dbus_string_insert_byte (str, pos, data_len))
776         goto oom;
777 
778       pos += 1;
779     }
780   else
781     {
782       if (!marshal_4_octets (str, pos, data_len,
783                              byte_order, &pos))
784         goto oom;
785     }
786 
787   if (!_dbus_string_copy_len (&value_str, 0, value_len,
788                               str, pos))
789     goto oom;
790 
791 #if 0
792   /* too expensive */
793   _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
794                                               str, pos));
795   _dbus_verbose_bytes_of_string (str, pos, value_len);
796 #endif
797 
798   pos += value_len;
799 
800   if (pos_after)
801     *pos_after = pos;
802 
803   return TRUE;
804 
805  oom:
806   /* Delete what we've inserted */
807   _dbus_string_delete (str, insert_at, pos - insert_at);
808 
809   return FALSE;
810 }
811 
812 static dbus_bool_t
marshal_string(DBusString * str,int insert_at,const char * value,int byte_order,int * pos_after)813 marshal_string (DBusString    *str,
814                 int            insert_at,
815                 const char    *value,
816                 int            byte_order,
817                 int           *pos_after)
818 {
819   return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
820                                         str, insert_at, value,
821                                         strlen (value),
822                                         byte_order, pos_after);
823 }
824 
825 static dbus_bool_t
marshal_signature(DBusString * str,int insert_at,const char * value,int * pos_after)826 marshal_signature (DBusString    *str,
827                    int            insert_at,
828                    const char    *value,
829                    int           *pos_after)
830 {
831   return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
832                                         str, insert_at, value,
833                                         strlen (value),
834                                         DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
835                                         pos_after);
836 }
837 
838 /**
839  * Marshals a basic-typed value. The "value" pointer is always the
840  * address of a variable containing the basic type value.
841  * So for example for int32 it will be dbus_int32_t*, and
842  * for string it will be const char**. This is for symmetry
843  * with _dbus_marshal_read_basic() and to have a simple
844  * consistent rule.
845  *
846  * @param str string to marshal to
847  * @param insert_at where to insert the value
848  * @param type type of value
849  * @param value pointer to a variable containing the value
850  * @param byte_order byte order
851  * @param pos_after #NULL or the position after the type
852  * @returns #TRUE on success
853  **/
854 dbus_bool_t
_dbus_marshal_write_basic(DBusString * str,int insert_at,int type,const void * value,int byte_order,int * pos_after)855 _dbus_marshal_write_basic (DBusString *str,
856                            int         insert_at,
857                            int         type,
858                            const void *value,
859                            int         byte_order,
860                            int        *pos_after)
861 {
862   const DBusBasicValue *vp;
863 
864   _dbus_assert (dbus_type_is_basic (type));
865 
866   vp = value;
867 
868   switch (type)
869     {
870     case DBUS_TYPE_BYTE:
871       if (!_dbus_string_insert_byte (str, insert_at, vp->byt))
872         return FALSE;
873       if (pos_after)
874         *pos_after = insert_at + 1;
875       return TRUE;
876       break;
877     case DBUS_TYPE_INT16:
878     case DBUS_TYPE_UINT16:
879       return marshal_2_octets (str, insert_at, vp->u16,
880                                byte_order, pos_after);
881       break;
882     case DBUS_TYPE_BOOLEAN:
883       return marshal_4_octets (str, insert_at, vp->u32 != FALSE,
884                                byte_order, pos_after);
885       break;
886     case DBUS_TYPE_INT32:
887     case DBUS_TYPE_UINT32:
888     case DBUS_TYPE_UNIX_FD:
889       return marshal_4_octets (str, insert_at, vp->u32,
890                                byte_order, pos_after);
891       break;
892     case DBUS_TYPE_INT64:
893     case DBUS_TYPE_UINT64:
894     case DBUS_TYPE_DOUBLE:
895       return marshal_8_octets (str, insert_at, *vp, byte_order, pos_after);
896       break;
897 
898     case DBUS_TYPE_STRING:
899     case DBUS_TYPE_OBJECT_PATH:
900       _dbus_assert (vp->str != NULL);
901       return marshal_string (str, insert_at, vp->str, byte_order, pos_after);
902       break;
903     case DBUS_TYPE_SIGNATURE:
904       _dbus_assert (vp->str != NULL);
905       return marshal_signature (str, insert_at, vp->str, pos_after);
906       break;
907     default:
908       _dbus_assert_not_reached ("not a basic type");
909       return FALSE;
910       break;
911     }
912 }
913 
914 static dbus_bool_t
marshal_1_octets_array(DBusString * str,int insert_at,const unsigned char * value,int n_elements,int byte_order,int * pos_after)915 marshal_1_octets_array (DBusString          *str,
916                         int                  insert_at,
917                         const unsigned char *value,
918                         int                  n_elements,
919                         int                  byte_order,
920                         int                 *pos_after)
921 {
922   int pos;
923   DBusString value_str;
924 
925   _dbus_string_init_const_len (&value_str, value, n_elements);
926 
927   pos = insert_at;
928 
929   if (!_dbus_string_copy_len (&value_str, 0, n_elements,
930                               str, pos))
931     return FALSE;
932 
933   pos += n_elements;
934 
935   if (pos_after)
936     *pos_after = pos;
937 
938   return TRUE;
939 }
940 
941 /**
942  * Swaps the elements of an array to the opposite byte order
943  *
944  * @param data start of array
945  * @param n_elements number of elements
946  * @param alignment size of each element
947  */
948 void
_dbus_swap_array(unsigned char * data,int n_elements,int alignment)949 _dbus_swap_array (unsigned char *data,
950                   int            n_elements,
951                   int            alignment)
952 {
953   unsigned char *d;
954   unsigned char *end;
955 
956   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, alignment) == data);
957 
958   /* we use const_data and cast it off so DBusString can be a const string
959    * for the unit tests. don't ask.
960    */
961   d = data;
962   end = d + (n_elements * alignment);
963 
964   if (alignment == 8)
965     {
966       while (d != end)
967         {
968 #ifdef DBUS_HAVE_INT64
969           *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
970 #else
971           swap_8_bytes ((DBusBasicValue*) d);
972 #endif
973           d += 8;
974         }
975     }
976   else if (alignment == 4)
977     {
978       while (d != end)
979         {
980           *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
981           d += 4;
982         }
983     }
984   else
985     {
986       _dbus_assert (alignment == 2);
987 
988       while (d != end)
989         {
990           *((dbus_uint16_t*)d) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)d));
991           d += 2;
992         }
993     }
994 }
995 
996 static void
swap_array(DBusString * str,int array_start,int n_elements,int byte_order,int alignment)997 swap_array (DBusString *str,
998             int         array_start,
999             int         n_elements,
1000             int         byte_order,
1001             int         alignment)
1002 {
1003   _dbus_assert (_DBUS_ALIGN_VALUE (array_start, alignment) == (unsigned) array_start);
1004 
1005   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1006     {
1007       /* we use const_data and cast it off so DBusString can be a const string
1008        * for the unit tests. don't ask.
1009        */
1010       _dbus_swap_array ((unsigned char*) (_dbus_string_get_const_data (str) + array_start),
1011                         n_elements, alignment);
1012     }
1013 }
1014 
1015 static dbus_bool_t
marshal_fixed_multi(DBusString * str,int insert_at,const DBusBasicValue * value,int n_elements,int byte_order,int alignment,int * pos_after)1016 marshal_fixed_multi (DBusString           *str,
1017                      int                   insert_at,
1018                      const DBusBasicValue *value,
1019                      int                   n_elements,
1020                      int                   byte_order,
1021                      int                   alignment,
1022                      int                  *pos_after)
1023 {
1024   int old_string_len;
1025   int array_start;
1026   DBusString t;
1027   int len_in_bytes;
1028 
1029   _dbus_assert (n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / alignment);
1030 
1031   old_string_len = _dbus_string_get_length (str);
1032 
1033   len_in_bytes = n_elements * alignment;
1034   array_start = insert_at;
1035 
1036   /* Note that we do alignment padding unconditionally
1037    * even if the array is empty; this means that
1038    * padding + len is always equal to the number of bytes
1039    * in the array.
1040    */
1041 
1042   if (!_dbus_string_insert_alignment (str, &array_start, alignment))
1043     goto error;
1044 
1045   _dbus_string_init_const_len (&t,
1046                                (const unsigned char*) value,
1047                                len_in_bytes);
1048 
1049   if (!_dbus_string_copy (&t, 0,
1050                           str, array_start))
1051     goto error;
1052 
1053   swap_array (str, array_start, n_elements, byte_order, alignment);
1054 
1055   if (pos_after)
1056     *pos_after = array_start + len_in_bytes;
1057 
1058   return TRUE;
1059 
1060  error:
1061   _dbus_string_delete (str, insert_at,
1062                        _dbus_string_get_length (str) - old_string_len);
1063 
1064   return FALSE;
1065 }
1066 
1067 /**
1068  * Marshals a block of values of fixed-length type all at once, as an
1069  * optimization.  dbus_type_is_fixed() returns #TRUE for fixed-length
1070  * types, which are the basic types minus the string-like types.
1071  *
1072  * The value argument should be the adddress of an
1073  * array, so e.g. "const dbus_uint32_t**"
1074  *
1075  * @param str string to marshal to
1076  * @param insert_at where to insert the value
1077  * @param element_type type of array elements
1078  * @param value address of an array to marshal
1079  * @param n_elements number of elements in the array
1080  * @param byte_order byte order
1081  * @param pos_after #NULL or the position after the type
1082  * @returns #TRUE on success
1083  **/
1084 dbus_bool_t
_dbus_marshal_write_fixed_multi(DBusString * str,int insert_at,int element_type,const void * value,int n_elements,int byte_order,int * pos_after)1085 _dbus_marshal_write_fixed_multi (DBusString *str,
1086                                  int         insert_at,
1087                                  int         element_type,
1088                                  const void *value,
1089                                  int         n_elements,
1090                                  int         byte_order,
1091                                  int        *pos_after)
1092 {
1093   const void* vp = *(const DBusBasicValue**)value;
1094 
1095   _dbus_assert (dbus_type_is_fixed (element_type));
1096   _dbus_assert (n_elements >= 0);
1097 
1098 #if 0
1099   _dbus_verbose ("writing %d elements of %s\n",
1100                  n_elements, _dbus_type_to_string (element_type));
1101 #endif
1102 
1103   switch (element_type)
1104     {
1105     case DBUS_TYPE_BYTE:
1106       return marshal_1_octets_array (str, insert_at, vp, n_elements, byte_order, pos_after);
1107       break;
1108     case DBUS_TYPE_INT16:
1109     case DBUS_TYPE_UINT16:
1110       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 2, pos_after);
1111     case DBUS_TYPE_BOOLEAN:
1112     case DBUS_TYPE_INT32:
1113     case DBUS_TYPE_UINT32:
1114     case DBUS_TYPE_UNIX_FD:
1115       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
1116       break;
1117     case DBUS_TYPE_INT64:
1118     case DBUS_TYPE_UINT64:
1119     case DBUS_TYPE_DOUBLE:
1120       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
1121       break;
1122 
1123     default:
1124       _dbus_assert_not_reached ("non fixed type in array write");
1125       break;
1126     }
1127 
1128   return FALSE;
1129 }
1130 
1131 
1132 /**
1133  * Skips over a basic-typed value, reporting the following position.
1134  *
1135  * @param str the string containing the data
1136  * @param type type of value to read
1137  * @param byte_order the byte order
1138  * @param pos pointer to position in the string,
1139  *            updated on return to new position
1140  **/
1141 void
_dbus_marshal_skip_basic(const DBusString * str,int type,int byte_order,int * pos)1142 _dbus_marshal_skip_basic (const DBusString      *str,
1143                           int                    type,
1144                           int                    byte_order,
1145                           int                   *pos)
1146 {
1147   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
1148                 byte_order == DBUS_BIG_ENDIAN);
1149 
1150   switch (type)
1151     {
1152     case DBUS_TYPE_BYTE:
1153       (*pos)++;
1154       break;
1155     case DBUS_TYPE_INT16:
1156     case DBUS_TYPE_UINT16:
1157       *pos = _DBUS_ALIGN_VALUE (*pos, 2);
1158       *pos += 2;
1159       break;
1160     case DBUS_TYPE_BOOLEAN:
1161     case DBUS_TYPE_INT32:
1162     case DBUS_TYPE_UINT32:
1163     case DBUS_TYPE_UNIX_FD:
1164       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
1165       *pos += 4;
1166       break;
1167     case DBUS_TYPE_INT64:
1168     case DBUS_TYPE_UINT64:
1169     case DBUS_TYPE_DOUBLE:
1170       *pos = _DBUS_ALIGN_VALUE (*pos, 8);
1171       *pos += 8;
1172       break;
1173     case DBUS_TYPE_STRING:
1174     case DBUS_TYPE_OBJECT_PATH:
1175       {
1176         int len;
1177 
1178         len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
1179 
1180         *pos += len + 1; /* length plus nul */
1181       }
1182       break;
1183     case DBUS_TYPE_SIGNATURE:
1184       {
1185         int len;
1186 
1187         len = _dbus_string_get_byte (str, *pos);
1188 
1189         *pos += len + 2; /* length byte plus length plus nul */
1190       }
1191       break;
1192     default:
1193       _dbus_warn ("type %s not a basic type\n",
1194                   _dbus_type_to_string (type));
1195       _dbus_assert_not_reached ("not a basic type");
1196       break;
1197     }
1198 }
1199 
1200 /**
1201  * Skips an array, returning the next position.
1202  *
1203  * @param str the string containing the data
1204  * @param element_type the type of array elements
1205  * @param byte_order the byte order
1206  * @param pos pointer to position in the string,
1207  *            updated on return to new position
1208  */
1209 void
_dbus_marshal_skip_array(const DBusString * str,int element_type,int byte_order,int * pos)1210 _dbus_marshal_skip_array (const DBusString  *str,
1211                           int                element_type,
1212                           int                byte_order,
1213                           int               *pos)
1214 {
1215   dbus_uint32_t array_len;
1216   int i;
1217   int alignment;
1218 
1219   i = _DBUS_ALIGN_VALUE (*pos, 4);
1220 
1221   array_len = _dbus_marshal_read_uint32 (str, i, byte_order, &i);
1222 
1223   alignment = _dbus_type_get_alignment (element_type);
1224 
1225   i = _DBUS_ALIGN_VALUE (i, alignment);
1226 
1227   *pos = i + array_len;
1228 }
1229 
1230 /**
1231  * Gets the alignment requirement for the given type;
1232  * will be 1, 4, or 8.
1233  *
1234  * @param typecode the type
1235  * @returns alignment of 1, 4, or 8
1236  */
1237 int
_dbus_type_get_alignment(int typecode)1238 _dbus_type_get_alignment (int typecode)
1239 {
1240   switch (typecode)
1241     {
1242     case DBUS_TYPE_BYTE:
1243     case DBUS_TYPE_VARIANT:
1244     case DBUS_TYPE_SIGNATURE:
1245       return 1;
1246     case DBUS_TYPE_INT16:
1247     case DBUS_TYPE_UINT16:
1248       return 2;
1249     case DBUS_TYPE_BOOLEAN:
1250     case DBUS_TYPE_INT32:
1251     case DBUS_TYPE_UINT32:
1252     case DBUS_TYPE_UNIX_FD:
1253       /* this stuff is 4 since it starts with a length */
1254     case DBUS_TYPE_STRING:
1255     case DBUS_TYPE_OBJECT_PATH:
1256     case DBUS_TYPE_ARRAY:
1257       return 4;
1258     case DBUS_TYPE_INT64:
1259     case DBUS_TYPE_UINT64:
1260     case DBUS_TYPE_DOUBLE:
1261       /* struct is 8 since it could contain an 8-aligned item
1262        * and it's simpler to just always align structs to 8;
1263        * we want the amount of padding in a struct of a given
1264        * type to be predictable, not location-dependent.
1265        * DICT_ENTRY is always the same as struct.
1266        */
1267     case DBUS_TYPE_STRUCT:
1268     case DBUS_TYPE_DICT_ENTRY:
1269       return 8;
1270 
1271     default:
1272       _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
1273       return 0;
1274     }
1275 }
1276 
1277 /**
1278  * Returns a string describing the given type.
1279  *
1280  * @param typecode the type to describe
1281  * @returns a constant string describing the type
1282  */
1283 const char *
_dbus_type_to_string(int typecode)1284 _dbus_type_to_string (int typecode)
1285 {
1286   switch (typecode)
1287     {
1288     case DBUS_TYPE_INVALID:
1289       return "invalid";
1290     case DBUS_TYPE_BOOLEAN:
1291       return "boolean";
1292     case DBUS_TYPE_BYTE:
1293       return "byte";
1294     case DBUS_TYPE_INT16:
1295       return "int16";
1296     case DBUS_TYPE_UINT16:
1297       return "uint16";
1298     case DBUS_TYPE_INT32:
1299       return "int32";
1300     case DBUS_TYPE_UINT32:
1301       return "uint32";
1302     case DBUS_TYPE_INT64:
1303       return "int64";
1304     case DBUS_TYPE_UINT64:
1305       return "uint64";
1306     case DBUS_TYPE_DOUBLE:
1307       return "double";
1308     case DBUS_TYPE_STRING:
1309       return "string";
1310     case DBUS_TYPE_OBJECT_PATH:
1311       return "object_path";
1312     case DBUS_TYPE_SIGNATURE:
1313       return "signature";
1314     case DBUS_TYPE_STRUCT:
1315       return "struct";
1316     case DBUS_TYPE_DICT_ENTRY:
1317       return "dict_entry";
1318     case DBUS_TYPE_ARRAY:
1319       return "array";
1320     case DBUS_TYPE_VARIANT:
1321       return "variant";
1322     case DBUS_STRUCT_BEGIN_CHAR:
1323       return "begin_struct";
1324     case DBUS_STRUCT_END_CHAR:
1325       return "end_struct";
1326     case DBUS_DICT_ENTRY_BEGIN_CHAR:
1327       return "begin_dict_entry";
1328     case DBUS_DICT_ENTRY_END_CHAR:
1329       return "end_dict_entry";
1330     case DBUS_TYPE_UNIX_FD:
1331       return "unix_fd";
1332     default:
1333       return "unknown";
1334     }
1335 }
1336 
1337 /**
1338  * If in verbose mode, print a block of binary data.
1339  *
1340  * @param data the data
1341  * @param len the length of the data
1342  * @param offset where to start counting for byte indexes
1343  */
1344 void
_dbus_verbose_bytes(const unsigned char * data,int len,int offset)1345 _dbus_verbose_bytes (const unsigned char *data,
1346                      int                  len,
1347                      int                  offset)
1348 {
1349   int i;
1350   const unsigned char *aligned;
1351 
1352   _dbus_assert (len >= 0);
1353 
1354   if (!_dbus_is_verbose())
1355     return;
1356 
1357   /* Print blanks on first row if appropriate */
1358   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
1359   if (aligned > data)
1360     aligned -= 4;
1361   _dbus_assert (aligned <= data);
1362 
1363   if (aligned != data)
1364     {
1365       _dbus_verbose ("%4ld\t%p: ", - (long)(data - aligned), aligned);
1366       while (aligned != data)
1367         {
1368           _dbus_verbose ("    ");
1369           ++aligned;
1370         }
1371     }
1372 
1373   /* now print the bytes */
1374   i = 0;
1375   while (i < len)
1376     {
1377       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1378         {
1379           _dbus_verbose ("%4d\t%p: ",
1380                          offset + i, &data[i]);
1381         }
1382 
1383       if (data[i] >= 32 &&
1384           data[i] <= 126)
1385         _dbus_verbose (" '%c' ", data[i]);
1386       else
1387         _dbus_verbose ("0x%s%x ",
1388                        data[i] <= 0xf ? "0" : "", data[i]);
1389 
1390       ++i;
1391 
1392       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1393         {
1394           if (i > 3)
1395             _dbus_verbose ("BE: %d LE: %d",
1396                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
1397                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
1398 
1399           if (i > 7 &&
1400               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
1401             {
1402 #ifdef DBUS_INT64_PRINTF_MODIFIER
1403               _dbus_verbose (" u64: 0x%" DBUS_INT64_PRINTF_MODIFIER "x",
1404                              *(dbus_uint64_t*)&data[i-8]);
1405 #endif
1406               _dbus_verbose (" dbl: %g",
1407                              *(double*)&data[i-8]);
1408             }
1409 
1410           _dbus_verbose ("\n");
1411         }
1412     }
1413 
1414   _dbus_verbose ("\n");
1415 }
1416 
1417 /**
1418  * Dump the given part of the string to verbose log.
1419  *
1420  * @param str the string
1421  * @param start the start of range to dump
1422  * @param len length of range
1423  */
1424 void
_dbus_verbose_bytes_of_string(const DBusString * str,int start,int len)1425 _dbus_verbose_bytes_of_string (const DBusString    *str,
1426                                int                  start,
1427                                int                  len)
1428 {
1429   const char *d;
1430   int real_len;
1431 
1432   real_len = _dbus_string_get_length (str);
1433 
1434   _dbus_assert (start >= 0);
1435 
1436   if (start > real_len)
1437     {
1438       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
1439                      start, len, real_len);
1440       return;
1441     }
1442 
1443   if ((start + len) > real_len)
1444     {
1445       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
1446                      start, len, real_len);
1447       len = real_len - start;
1448     }
1449 
1450   d = _dbus_string_get_const_data_len (str, start, len);
1451 
1452   _dbus_verbose_bytes (d, len, start);
1453 }
1454 
1455 static int
map_type_char_to_type(int t)1456 map_type_char_to_type (int t)
1457 {
1458   if (t == DBUS_STRUCT_BEGIN_CHAR)
1459     return DBUS_TYPE_STRUCT;
1460   else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR)
1461     return DBUS_TYPE_DICT_ENTRY;
1462   else
1463     {
1464       _dbus_assert (t != DBUS_STRUCT_END_CHAR);
1465       _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
1466       return t;
1467     }
1468 }
1469 
1470 /**
1471  * Get the first type in the signature. The difference between this
1472  * and just getting the first byte of the signature is that you won't
1473  * get DBUS_STRUCT_BEGIN_CHAR, you'll get DBUS_TYPE_STRUCT
1474  * instead.
1475  *
1476  * @param str string containing signature
1477  * @param pos where the signature starts
1478  * @returns the first type in the signature
1479  */
1480 int
_dbus_first_type_in_signature(const DBusString * str,int pos)1481 _dbus_first_type_in_signature (const DBusString *str,
1482                                int               pos)
1483 {
1484   return map_type_char_to_type (_dbus_string_get_byte (str, pos));
1485 }
1486 
1487 /**
1488  * Similar to #_dbus_first_type_in_signature, but operates
1489  * on a C string buffer.
1490  *
1491  * @param str a C string buffer
1492  * @param pos where the signature starts
1493  * @returns the first type in the signature
1494  */
1495 int
_dbus_first_type_in_signature_c_str(const char * str,int pos)1496 _dbus_first_type_in_signature_c_str (const char       *str,
1497 				     int               pos)
1498 {
1499   return map_type_char_to_type (str[pos]);
1500 }
1501 
1502 /** @} */
1503 
1504 #ifdef DBUS_BUILD_TESTS
1505 #include "dbus-test.h"
1506 #include <stdio.h>
1507 
1508 /**
1509  * Reads a block of fixed-length basic values, as an optimization
1510  * vs. reading each one individually into a new buffer.
1511  *
1512  * This function returns the data in-place; it does not make a copy,
1513  * and it does not swap the bytes.
1514  *
1515  * If you ask for #DBUS_TYPE_DOUBLE you will get a "const double*" back
1516  * and the "value" argument should be a "const double**" and so on.
1517  *
1518  * @param str the string to read from
1519  * @param pos position to read from
1520  * @param element_type type of array elements
1521  * @param value place to return the array
1522  * @param n_elements number of array elements to read
1523  * @param byte_order the byte order, used to read the array length
1524  * @param new_pos #NULL or location to store a position after the elements
1525  */
1526 void
_dbus_marshal_read_fixed_multi(const DBusString * str,int pos,int element_type,void * value,int n_elements,int byte_order,int * new_pos)1527 _dbus_marshal_read_fixed_multi  (const DBusString *str,
1528                                  int               pos,
1529                                  int               element_type,
1530                                  void             *value,
1531                                  int               n_elements,
1532                                  int               byte_order,
1533                                  int              *new_pos)
1534 {
1535   int array_len;
1536   int alignment;
1537 
1538   _dbus_assert (dbus_type_is_fixed (element_type));
1539   _dbus_assert (dbus_type_is_basic (element_type));
1540 
1541 #if 0
1542   _dbus_verbose ("reading %d elements of %s\n",
1543                  n_elements, _dbus_type_to_string (element_type));
1544 #endif
1545 
1546   alignment = _dbus_type_get_alignment (element_type);
1547 
1548   pos = _DBUS_ALIGN_VALUE (pos, alignment);
1549 
1550   array_len = n_elements * alignment;
1551 
1552   *(const DBusBasicValue**) value = (void*) _dbus_string_get_const_data_len (str, pos, array_len);
1553   if (new_pos)
1554     *new_pos = pos + array_len;
1555 }
1556 
1557 static void
swap_test_array(void * array,int len_bytes,int byte_order,int alignment)1558 swap_test_array (void *array,
1559                  int   len_bytes,
1560                  int   byte_order,
1561                  int   alignment)
1562 {
1563   DBusString t;
1564 
1565   if (alignment == 1)
1566     return;
1567 
1568   _dbus_string_init_const_len (&t, array, len_bytes);
1569   swap_array (&t, 0, len_bytes / alignment, byte_order, alignment);
1570 }
1571 
1572 #define MARSHAL_BASIC(typename, byte_order, literal)                    \
1573   do {                                                                  \
1574      v_##typename = literal;                                            \
1575      if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_##typename,   \
1576                                     &v_##typename,                      \
1577                                     byte_order, NULL))                  \
1578        _dbus_assert_not_reached ("no memory");                          \
1579    } while (0)
1580 
1581 #define DEMARSHAL_BASIC(typename, byte_order)                                   \
1582   do {                                                                          \
1583     _dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename,   \
1584                               byte_order, &pos);                                \
1585   } while (0)
1586 
1587 #define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal)                        \
1588   do {                                                                                  \
1589     DEMARSHAL_BASIC (typename, byte_order);                                             \
1590     if (literal != v_##typename)                                                        \
1591       {                                                                                 \
1592         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
1593                                      _dbus_string_get_length (&str) - dump_pos);        \
1594         _dbus_assert_not_reached ("demarshaled wrong value");                           \
1595       }                                                                                 \
1596   } while (0)
1597 
1598 #define MARSHAL_TEST(typename, byte_order, literal)             \
1599   do {                                                          \
1600     MARSHAL_BASIC (typename, byte_order, literal);              \
1601     dump_pos = pos;                                             \
1602     DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal);  \
1603   } while (0)
1604 
1605 #define MARSHAL_TEST_STRCMP(typename, byte_order, literal)                              \
1606   do {                                                                                  \
1607     MARSHAL_BASIC (typename, byte_order, literal);                                      \
1608     dump_pos = pos;                                                                     \
1609     DEMARSHAL_BASIC (typename, byte_order);                                             \
1610     if (strcmp (literal, v_##typename) != 0)                                            \
1611       {                                                                                 \
1612         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
1613                                        _dbus_string_get_length (&str) - dump_pos);      \
1614         _dbus_warn ("literal '%s'\nvalue  '%s'\n", literal, v_##typename);              \
1615         _dbus_assert_not_reached ("demarshaled wrong value");                           \
1616       }                                                                                 \
1617   } while (0)
1618 
1619 #define MARSHAL_FIXED_ARRAY(typename, byte_order, literal)                                      \
1620   do {                                                                                          \
1621      int next;                                                                                  \
1622      v_UINT32 = sizeof(literal);                                                                \
1623      if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_UINT32, &v_UINT32,                    \
1624                                      byte_order, &next))                                        \
1625        _dbus_assert_not_reached ("no memory");                                                  \
1626      v_ARRAY_##typename = literal;                                                              \
1627      if (!_dbus_marshal_write_fixed_multi (&str, next, DBUS_TYPE_##typename,                    \
1628                                            &v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal),      \
1629                                            byte_order, NULL))                                   \
1630        _dbus_assert_not_reached ("no memory");                                                  \
1631    } while (0)
1632 
1633 #define DEMARSHAL_FIXED_ARRAY(typename, byte_order)                                             \
1634   do {                                                                                          \
1635     int next;                                                                                   \
1636     alignment = _dbus_type_get_alignment (DBUS_TYPE_##typename);                                \
1637     v_UINT32 = _dbus_marshal_read_uint32 (&str, dump_pos, byte_order, &next);                   \
1638     _dbus_marshal_read_fixed_multi (&str, next, DBUS_TYPE_##typename, &v_ARRAY_##typename,      \
1639                                     v_UINT32/alignment,                                         \
1640                                     byte_order, NULL);                                          \
1641     swap_test_array (v_ARRAY_##typename, v_UINT32,                                              \
1642                      byte_order, alignment);                                                    \
1643   } while (0)
1644 
1645 #define DEMARSHAL_FIXED_ARRAY_AND_CHECK(typename, byte_order, literal)                  \
1646   do {                                                                                  \
1647     DEMARSHAL_FIXED_ARRAY (typename, byte_order);                                       \
1648     if (memcmp (literal, v_ARRAY_##typename, sizeof (literal) != 0))                    \
1649       {                                                                                 \
1650         _dbus_verbose ("MARSHALED DATA\n");                                             \
1651         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
1652                                       _dbus_string_get_length (&str) - dump_pos);       \
1653         _dbus_verbose ("LITERAL DATA\n");                                               \
1654         _dbus_verbose_bytes ((char*)literal, sizeof (literal), 0);                      \
1655         _dbus_verbose ("READ DATA\n");                                                  \
1656         _dbus_verbose_bytes ((char*)v_ARRAY_##typename, sizeof (literal), 0);           \
1657         _dbus_assert_not_reached ("demarshaled wrong fixed array value");               \
1658       }                                                                                 \
1659   } while (0)
1660 
1661 #define MARSHAL_TEST_FIXED_ARRAY(typename, byte_order, literal)         \
1662   do {                                                                  \
1663     MARSHAL_FIXED_ARRAY (typename, byte_order, literal);                \
1664     dump_pos = pos;                                                     \
1665     DEMARSHAL_FIXED_ARRAY_AND_CHECK (typename, byte_order, literal);    \
1666   } while (0)
1667 
1668 dbus_bool_t
_dbus_marshal_test(void)1669 _dbus_marshal_test (void)
1670 {
1671   int alignment;
1672   DBusString str;
1673   int pos, dump_pos;
1674   unsigned char array1[5] = { 3, 4, 0, 1, 9 };
1675   dbus_int16_t array2[3] = { 124, 457, 780 };
1676   dbus_int32_t array4[3] = { 123, 456, 789 };
1677 #ifdef DBUS_HAVE_INT64
1678   dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
1679                              DBUS_INT64_CONSTANT (0x456ffffffff),
1680                              DBUS_INT64_CONSTANT (0x789ffffffff) };
1681   dbus_int64_t *v_ARRAY_INT64;
1682 #endif
1683   unsigned char *v_ARRAY_BYTE;
1684   dbus_int16_t *v_ARRAY_INT16;
1685   dbus_uint16_t *v_ARRAY_UINT16;
1686   dbus_int32_t *v_ARRAY_INT32;
1687   dbus_uint32_t *v_ARRAY_UINT32;
1688   DBusString t;
1689   double v_DOUBLE;
1690   double t_DOUBLE;
1691   dbus_int16_t v_INT16;
1692   dbus_uint16_t v_UINT16;
1693   dbus_int32_t v_INT32;
1694   dbus_uint32_t v_UINT32;
1695   dbus_int64_t v_INT64;
1696   dbus_uint64_t v_UINT64;
1697   unsigned char v_BYTE;
1698   dbus_bool_t v_BOOLEAN;
1699   const char *v_STRING;
1700   const char *v_SIGNATURE;
1701   const char *v_OBJECT_PATH;
1702   int byte_order;
1703 
1704   if (!_dbus_string_init (&str))
1705     _dbus_assert_not_reached ("failed to init string");
1706 
1707   pos = 0;
1708 
1709   /* Marshal doubles */
1710   MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14);
1711   DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN);
1712   t_DOUBLE = 3.14;
1713   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
1714     _dbus_assert_not_reached ("got wrong double value");
1715 
1716   MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14);
1717   DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN);
1718   t_DOUBLE = 3.14;
1719   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
1720     _dbus_assert_not_reached ("got wrong double value");
1721 
1722   /* Marshal signed 16 integers */
1723   MARSHAL_TEST (INT16, DBUS_BIG_ENDIAN, -12345);
1724   MARSHAL_TEST (INT16, DBUS_LITTLE_ENDIAN, -12345);
1725 
1726   /* Marshal unsigned 16 integers */
1727   MARSHAL_TEST (UINT16, DBUS_BIG_ENDIAN, 0x1234);
1728   MARSHAL_TEST (UINT16, DBUS_LITTLE_ENDIAN, 0x1234);
1729 
1730   /* Marshal signed integers */
1731   MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
1732   MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
1733 
1734   /* Marshal unsigned integers */
1735   MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678);
1736   MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678);
1737 
1738 #ifdef DBUS_HAVE_INT64
1739   /* Marshal signed integers */
1740   MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
1741   MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
1742 
1743   /* Marshal unsigned integers */
1744   MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
1745   MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
1746 #endif /* DBUS_HAVE_INT64 */
1747 
1748   /* Marshal byte */
1749   MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5);
1750   MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5);
1751 
1752   /* Marshal all possible bools! */
1753   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE);
1754   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE);
1755   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE);
1756   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE);
1757 
1758   /* Marshal strings */
1759   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "");
1760   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "");
1761   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string");
1762   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string");
1763 
1764   /* object paths */
1765   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c");
1766   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c");
1767 
1768   /* signatures */
1769   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "");
1770   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "");
1771   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
1772   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
1773 
1774   /* Arrays */
1775   MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_BIG_ENDIAN, array2);
1776   MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_LITTLE_ENDIAN, array2);
1777   MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_BIG_ENDIAN, array2);
1778   MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_LITTLE_ENDIAN, array2);
1779 
1780   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
1781   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
1782   MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_BIG_ENDIAN, array4);
1783   MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_LITTLE_ENDIAN, array4);
1784 
1785   MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1);
1786   MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1);
1787 
1788 #ifdef DBUS_HAVE_INT64
1789   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
1790   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
1791 #endif
1792 
1793 #if 0
1794 
1795   /*
1796    * FIXME restore the set/pack tests
1797    */
1798 
1799 #ifdef DBUS_HAVE_INT64
1800   /* set/pack 64-bit integers */
1801   _dbus_string_set_length (&str, 8);
1802 
1803   /* signed little */
1804   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
1805                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
1806 
1807   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1808                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
1809                                     _dbus_string_get_const_data (&str)));
1810 
1811   /* signed big */
1812   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
1813                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
1814 
1815   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1816                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
1817                                     _dbus_string_get_const_data (&str)));
1818 
1819   /* signed little pack */
1820   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
1821                     DBUS_LITTLE_ENDIAN,
1822                     _dbus_string_get_data (&str));
1823 
1824   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1825                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
1826                                     _dbus_string_get_const_data (&str)));
1827 
1828   /* signed big pack */
1829   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
1830                     DBUS_BIG_ENDIAN,
1831                     _dbus_string_get_data (&str));
1832 
1833   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1834                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
1835                                     _dbus_string_get_const_data (&str)));
1836 
1837   /* unsigned little */
1838   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
1839                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
1840 
1841   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1842                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
1843                                      _dbus_string_get_const_data (&str)));
1844 
1845   /* unsigned big */
1846   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
1847                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
1848 
1849   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1850                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
1851                                      _dbus_string_get_const_data (&str)));
1852 
1853   /* unsigned little pack */
1854   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
1855                      DBUS_LITTLE_ENDIAN,
1856                      _dbus_string_get_data (&str));
1857 
1858   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1859                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
1860                                      _dbus_string_get_const_data (&str)));
1861 
1862   /* unsigned big pack */
1863   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
1864                      DBUS_BIG_ENDIAN,
1865                      _dbus_string_get_data (&str));
1866 
1867   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1868                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
1869                                      _dbus_string_get_const_data (&str)));
1870 #endif /* DBUS_HAVE_INT64 */
1871 
1872   /* set/pack 32-bit integers */
1873   _dbus_string_set_length (&str, 4);
1874 
1875   /* signed little */
1876   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
1877                            0, -0x123456);
1878 
1879   _dbus_assert (-0x123456 ==
1880                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
1881                                     _dbus_string_get_const_data (&str)));
1882 
1883   /* signed big */
1884   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
1885                            0, -0x123456);
1886 
1887   _dbus_assert (-0x123456 ==
1888                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
1889                                     _dbus_string_get_const_data (&str)));
1890 
1891   /* signed little pack */
1892   _dbus_pack_int32 (-0x123456,
1893                     DBUS_LITTLE_ENDIAN,
1894                     _dbus_string_get_data (&str));
1895 
1896   _dbus_assert (-0x123456 ==
1897                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
1898                                     _dbus_string_get_const_data (&str)));
1899 
1900   /* signed big pack */
1901   _dbus_pack_int32 (-0x123456,
1902                     DBUS_BIG_ENDIAN,
1903                     _dbus_string_get_data (&str));
1904 
1905   _dbus_assert (-0x123456 ==
1906                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
1907                                     _dbus_string_get_const_data (&str)));
1908 
1909   /* unsigned little */
1910   _dbus_marshal_set_uint32 (&str,
1911                             0, 0x123456,
1912                             DBUS_LITTLE_ENDIAN);
1913 
1914   _dbus_assert (0x123456 ==
1915                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
1916                                      _dbus_string_get_const_data (&str)));
1917 
1918   /* unsigned big */
1919   _dbus_marshal_set_uint32 (&str,
1920                             0, 0x123456,
1921                             DBUS_BIG_ENDIAN);
1922 
1923   _dbus_assert (0x123456 ==
1924                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
1925                                      _dbus_string_get_const_data (&str)));
1926 
1927   /* unsigned little pack */
1928   _dbus_pack_uint32 (0x123456,
1929                      DBUS_LITTLE_ENDIAN,
1930                      _dbus_string_get_data (&str));
1931 
1932   _dbus_assert (0x123456 ==
1933                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
1934                                      _dbus_string_get_const_data (&str)));
1935 
1936   /* unsigned big pack */
1937   _dbus_pack_uint32 (0x123456,
1938                      DBUS_BIG_ENDIAN,
1939                      _dbus_string_get_data (&str));
1940 
1941   _dbus_assert (0x123456 ==
1942                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
1943                                      _dbus_string_get_const_data (&str)));
1944 
1945 #endif /* set/pack tests for integers */
1946 
1947   /* Strings in-place set */
1948   byte_order = DBUS_LITTLE_ENDIAN;
1949   while (TRUE)
1950     {
1951       /* Init a string */
1952       _dbus_string_set_length (&str, 0);
1953 
1954       /* reset pos for the macros */
1955       pos = 0;
1956 
1957       MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world");
1958 
1959       /* Set it to something longer */
1960       _dbus_string_init_const (&t, "Hello world foo");
1961 
1962       v_STRING = _dbus_string_get_const_data (&t);
1963       _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
1964                                &v_STRING, byte_order, NULL, NULL);
1965 
1966       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
1967                                 &v_STRING, byte_order,
1968                                 NULL);
1969       _dbus_assert (strcmp (v_STRING, "Hello world foo") == 0);
1970 
1971       /* Set it to something shorter */
1972       _dbus_string_init_const (&t, "Hello");
1973 
1974       v_STRING = _dbus_string_get_const_data (&t);
1975       _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
1976                                &v_STRING, byte_order, NULL, NULL);
1977       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
1978                                 &v_STRING, byte_order,
1979                                 NULL);
1980       _dbus_assert (strcmp (v_STRING, "Hello") == 0);
1981 
1982       /* Do the other byte order */
1983       if (byte_order == DBUS_LITTLE_ENDIAN)
1984         byte_order = DBUS_BIG_ENDIAN;
1985       else
1986         break;
1987     }
1988 
1989   /* Clean up */
1990   _dbus_string_free (&str);
1991 
1992   return TRUE;
1993 }
1994 
1995 #endif /* DBUS_BUILD_TESTS */
1996