Update some paths in HACKING
[platform/upstream/dbus.git] / dbus / dbus-marshal.c
index 82de8ff..00821da 100644 (file)
@@ -2,9 +2,9 @@
 /* dbus-marshal.c  Marshalling routines
  *
  * Copyright (C) 2002 CodeFactory AB
- * Copyright (C) 2003 Red Hat, Inc.
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
  *
- * Licensed under the Academic Free License version 1.2
+ * Licensed under the Academic Free License version 2.1
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -73,13 +73,17 @@ swap_bytes (unsigned char *data,
 }
 #endif /* !DBUS_HAVE_INT64 */
 
+/**
+ * Union used to manipulate 8 bytes as if they
+ * were various types. 
+ */
 typedef union
 {
 #ifdef DBUS_HAVE_INT64
-  dbus_int64_t  s;
-  dbus_uint64_t u;
+  dbus_int64_t  s; /**< 64-bit integer */
+  dbus_uint64_t u; /**< 64-bit unsinged integer */
 #endif
-  double d;
+  double d;        /**< double */
 } DBusOctets8;
 
 static DBusOctets8
@@ -98,7 +102,8 @@ unpack_8_octets (int                  byte_order,
     r.u = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
 #else
   r.d = *(double*)data;
-  swap_bytes (&r, sizeof (r));
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    swap_bytes ((unsigned char*) &r, sizeof (r));
 #endif
   
   return r;
@@ -342,7 +347,7 @@ _dbus_marshal_set_uint32 (DBusString          *str,
 #ifdef DBUS_HAVE_INT64
 
 /**
- * Sets the 4 bytes at the given offset to a marshaled signed integer,
+ * Sets the 8 bytes at the given offset to a marshaled signed integer,
  * replacing anything found there previously.
  *
  * @param str the string to write the marshalled int to
@@ -363,7 +368,7 @@ _dbus_marshal_set_int64 (DBusString          *str,
 }
 
 /**
- * Sets the 4 bytes at the given offset to a marshaled unsigned
+ * Sets the 8 bytes at the given offset to a marshaled unsigned
  * integer, replacing anything found there previously.
  *
  * @param str the string to write the marshalled int to
@@ -390,6 +395,10 @@ _dbus_marshal_set_uint64 (DBusString          *str,
  * an existing string or the wrong length will be deleted
  * and replaced with the new string.
  *
+ * Note: no attempt is made by this function to re-align
+ * any data which has been already marshalled after this
+ * string. Use with caution.
+ *
  * @param str the string to write the marshalled string to
  * @param offset the byte offset where string should be written
  * @param byte_order the byte order to use
@@ -423,6 +432,30 @@ _dbus_marshal_set_string (DBusString          *str,
   return TRUE;
 }
 
+/**
+ * Sets the existing marshaled object path at the given offset to a new
+ * value. The given offset must point to an existing object path or this
+ * function doesn't make sense.
+ *
+ * @todo implement this function
+ *
+ * @param str the string to write the marshalled path to
+ * @param offset the byte offset where path should be written
+ * @param byte_order the byte order to use
+ * @param path the new path
+ * @param path_len number of elements in the path
+ */
+void
+_dbus_marshal_set_object_path (DBusString         *str,
+                               int                 byte_order,
+                               int                 offset,
+                               const char        **path,
+                               int                 path_len)
+{
+
+  /* FIXME */
+}
+
 static dbus_bool_t
 marshal_4_octets (DBusString   *str,
                   int           byte_order,
@@ -430,13 +463,11 @@ marshal_4_octets (DBusString   *str,
 {
   _dbus_assert (sizeof (value) == 4);
   
-  if (!_dbus_string_align_length (str, sizeof (dbus_uint32_t)))
-    return FALSE;
-  
   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
     value = DBUS_UINT32_SWAP_LE_BE (value);
 
-  return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_uint32_t));
+  return _dbus_string_append_4_aligned (str,
+                                        (const unsigned char *)&value);
 }
 
 static dbus_bool_t
@@ -445,14 +476,12 @@ marshal_8_octets (DBusString *str,
                   DBusOctets8 value)
 {
   _dbus_assert (sizeof (value) == 8);
-
-  if (!_dbus_string_align_length (str, 8))
-    return FALSE;
   
   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
     pack_8_octets (value, byte_order, (unsigned char*) &value); /* pack into self, swapping as we go */
 
-  return _dbus_string_append_len (str, (const char *)&value, 8);
+  return _dbus_string_append_8_aligned (str,
+                                        (const unsigned char *)&value);
 }
 
 /**
@@ -579,6 +608,46 @@ _dbus_marshal_string (DBusString    *str,
 }
 
 /**
+ * Marshals a UTF-8 string
+ *
+ * @todo: If the string append fails we need to restore
+ * the old length. (also for other marshallers)
+ * 
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param value the string
+ * @param len length of string to marshal in bytes
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_marshal_string_len (DBusString    *str,
+                          int            byte_order,
+                          const char    *value,
+                          int            len)
+{
+  int old_string_len;
+
+  old_string_len = _dbus_string_get_length (str);
+
+  if (!_dbus_marshal_uint32 (str, byte_order, len))
+    {
+      /* Restore the previous length */
+      _dbus_string_set_length (str, old_string_len);
+
+      return FALSE;
+    }
+
+  if (!_dbus_string_append_len (str, value, len))
+    return FALSE;
+
+  /* add a nul byte */
+  if (!_dbus_string_lengthen (str, 1))
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
  * Marshals a byte array
  *
  * @param str the string to append the marshalled value to
@@ -686,7 +755,7 @@ marshal_8_octets_array (DBusString          *str,
 #ifdef DBUS_HAVE_INT64
           *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
 #else
-          swap_bytes (d, 8);
+          swap_bytes ((unsigned char*) d, 8);
 #endif
           d += 8;
         }
@@ -848,6 +917,58 @@ _dbus_marshal_string_array (DBusString  *str,
   return FALSE;      
 }
 
+/**
+ * Marshals an object path value.
+ * 
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param path the path
+ * @param path_len length of the path
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_marshal_object_path (DBusString            *str,
+                           int                    byte_order,
+                           const char           **path,
+                           int                    path_len)
+{
+  int array_start, old_string_len;
+  int i;
+  
+  old_string_len = _dbus_string_get_length (str);
+  
+  /* Set the length to 0 temporarily */
+  if (!_dbus_marshal_uint32 (str, byte_order, 0))
+    goto nomem;
+
+  array_start = _dbus_string_get_length (str);
+  
+  i = 0;
+  while (i < path_len)
+    {
+      if (!_dbus_string_append_byte (str, '/'))
+        goto nomem;
+      
+      if (!_dbus_string_append (str, path[0]))
+        goto nomem;
+
+      ++i;
+    }
+
+  /* Write the length now that we know it */
+  _dbus_marshal_set_uint32 (str, byte_order,
+                           _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
+                           _dbus_string_get_length (str) - array_start);  
+
+  return TRUE;
+
+ nomem:
+  /* Restore the previous length */
+  _dbus_string_set_length (str, old_string_len);
+  
+  return FALSE;
+}
+
 static dbus_uint32_t
 demarshal_4_octets (const DBusString *str,
                     int               byte_order,
@@ -987,6 +1108,61 @@ _dbus_demarshal_uint64  (const DBusString *str,
 #endif /* DBUS_HAVE_INT64 */
 
 /**
+ * Demarshals a basic type
+ *
+ * @param str the string containing the data
+ * @param type type of value to demarshal
+ * @param value pointer to return value data
+ * @param byte_order the byte order
+ * @param pos pointer to position in the string,
+ *            updated on return to new position
+ **/
+void
+_dbus_demarshal_basic_type (const DBusString      *str,
+                           int                    type,
+                           void                  *value,
+                           int                    byte_order,
+                           int                   *pos)
+{
+  const char *str_data = _dbus_string_get_const_data (str);
+
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+      *(unsigned char *) value = _dbus_string_get_byte (str, *pos);
+      (*pos)++;
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      *pos = _DBUS_ALIGN_VALUE (*pos, 4);
+      *(dbus_uint32_t *) value = *(dbus_uint32_t *)(str_data + *pos);
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+       *(dbus_uint32_t *) value = DBUS_UINT32_SWAP_LE_BE (*(dbus_uint32_t *) value);
+      *pos += 4;
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      *pos = _DBUS_ALIGN_VALUE (*pos, 8);
+      memcpy (value, str_data + *pos, 8);
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+#ifdef DBUS_HAVE_INT64
+       *(dbus_uint64_t *) value = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t *) value);
+#else  
+       swap_bytes (value, 8);
+#endif
+      *pos += 8;
+      break;
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
+}
+
+/**
  * Demarshals an UTF-8 string.
  *
  * @todo Should we check the string to make sure
@@ -1178,7 +1354,7 @@ demarshal_8_octets_array (const DBusString  *str,
 #ifdef DBUS_HAVE_INT64
           retval[i].u = DBUS_UINT64_SWAP_LE_BE (retval[i].u);
 #else
-          swap_bytes (&retval[i], 8);
+          swap_bytes ((unsigned char *) &retval[i], 8);
 #endif
         }
     }
@@ -1311,6 +1487,53 @@ _dbus_demarshal_double_array (const DBusString  *str,
                                    (DBusOctets8**) array, array_len);
 }
 
+
+/**
+ * Demarshals an array of basic types
+ *
+ * @param str the string containing the data
+ * @param element_type type of array elements to demarshal
+ * @param array pointer to pointer to array data
+ * @param array_len pointer to array length
+ * @param byte_order the byte order
+ * @param pos pointer to position in the string,
+ *            updated on return to new position
+ **/
+dbus_bool_t
+_dbus_demarshal_basic_type_array (const DBusString      *str,
+                                 int                    element_type,
+                                 void                 **array,
+                                 int                   *array_len,
+                                 int                    byte_order,
+                                 int                   *pos)
+{
+  switch (element_type)
+    {
+    case DBUS_TYPE_BOOLEAN:
+      /* FIXME: do we want to post-normalize these ? */
+    case DBUS_TYPE_BYTE:
+      return _dbus_demarshal_byte_array (str, byte_order, *pos, pos,
+                                        (unsigned char **)array, array_len);
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      return demarshal_4_octets_array (str, byte_order, *pos, pos,
+                                      (dbus_uint32_t **)array, array_len);
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      return demarshal_8_octets_array (str, byte_order, *pos, pos,
+                                      (DBusOctets8**) array, array_len);
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
+  return FALSE;
+}
+
 /**
  * Demarshals a string array.
  *
@@ -1319,7 +1542,7 @@ _dbus_demarshal_double_array (const DBusString  *str,
  * @param pos the position in the string
  * @param new_pos the new position of the string
  * @param array the array
- * @param array_len length of the demarshaled data
+ * @param array_len location for length of the demarshaled data or NULL
  * @returns #TRUE on success
  */
 dbus_bool_t
@@ -1397,6 +1620,128 @@ _dbus_demarshal_string_array (const DBusString   *str,
   return FALSE;
 }
 
+/** Set to 1 to get a bunch of spew about disassembling the path string */
+#define VERBOSE_DECOMPOSE 0
+
+/**
+ * Decompose an object path.  A path of just "/" is
+ * represented as an empty vector of strings.
+ * 
+ * @param data the path data
+ * @param len  the length of the path string
+ * @param path address to store new object path
+ * @param path_len length of stored path
+ */
+dbus_bool_t
+_dbus_decompose_path (const char*     data,
+                      int             len,
+                      char         ***path,
+                      int            *path_len)
+{
+  char **retval;
+  int n_components;
+  int i, j, comp;
+
+  _dbus_assert (data != NULL);
+
+#if VERBOSE_DECOMPOSE
+  _dbus_verbose ("Decomposing path \"%s\"\n",
+                 data);
+#endif
+  
+  n_components = 0;
+  i = 0;
+  while (i < len)
+    {
+      if (data[i] == '/')
+        n_components += 1;
+      ++i;
+    }
+  
+  retval = dbus_new0 (char*, n_components + 1);
+
+  if (retval == NULL)
+    return FALSE;
+
+  comp = 0;
+  i = 0;
+  while (i < len)
+    {
+      if (data[i] == '/')
+        ++i;
+      j = i;
+
+      while (j < len && data[j] != '/')
+        ++j;
+
+      /* Now [i, j) is the path component */
+      _dbus_assert (i < j);
+      _dbus_assert (data[i] != '/');
+      _dbus_assert (j == len || data[j] == '/');
+
+#if VERBOSE_DECOMPOSE
+      _dbus_verbose ("  (component in [%d,%d))\n",
+                     i, j);
+#endif
+      
+      retval[comp] = _dbus_memdup (&data[i], j - i + 1);
+      if (retval[comp] == NULL)
+        {
+          dbus_free_string_array (retval);
+          return FALSE;
+        }
+      retval[comp][j-i] = '\0';
+#if VERBOSE_DECOMPOSE
+      _dbus_verbose ("  (component %d = \"%s\")\n",
+                     comp, retval[comp]);
+#endif
+
+      ++comp;
+      i = j;
+    }
+  _dbus_assert (i == len);
+  
+  *path = retval;
+  if (path_len)
+    *path_len = n_components;
+  
+  return TRUE;
+}
+
+/**
+ * Demarshals an object path.  A path of just "/" is
+ * represented as an empty vector of strings.
+ * 
+ * @param str the string containing the data
+ * @param byte_order the byte order
+ * @param pos the position in the string
+ * @param new_pos the new position of the string
+ * @param path address to store new object path
+ * @param path_len length of stored path
+ */
+dbus_bool_t
+_dbus_demarshal_object_path (const DBusString *str,
+                             int               byte_order,
+                             int               pos,
+                             int              *new_pos,
+                             char           ***path,
+                             int              *path_len)
+{
+  int len;
+  const char *data;
+  
+  len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+  data = _dbus_string_get_const_data_len (str, pos, len + 1);
+
+  if (!_dbus_decompose_path (data, len, path, path_len))
+    return FALSE;
+
+  if (new_pos)
+    *new_pos = pos + len + 1;
+
+  return TRUE;
+}
+
 /** 
  * Returns the position right after the end of an argument.  PERFORMS
  * NO VALIDATION WHATSOEVER. The message must have been previously
@@ -1439,32 +1784,18 @@ _dbus_marshal_get_arg_end_pos (const DBusString *str,
       break;
 
     case DBUS_TYPE_INT32:
-      *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
-
-      break;
-
     case DBUS_TYPE_UINT32:
-      *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
-
+      *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
       break;
 
-#ifdef DBUS_HAVE_INT64
     case DBUS_TYPE_INT64:
-      *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int64_t)) + sizeof (dbus_int64_t);
-
-      break;
-
     case DBUS_TYPE_UINT64:
-      *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint64_t)) + sizeof (dbus_uint64_t);
-
-      break;
-#endif /* DBUS_HAVE_INT64 */
-      
     case DBUS_TYPE_DOUBLE:
-      *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (double)) + sizeof (double);
-
+      
+      *end_pos = _DBUS_ALIGN_VALUE (pos, 8) + 8;
       break;
 
+    case DBUS_TYPE_OBJECT_PATH:
     case DBUS_TYPE_STRING:
       {
        int len;
@@ -1476,14 +1807,14 @@ _dbus_marshal_get_arg_end_pos (const DBusString *str,
       }
       break;
 
-    case DBUS_TYPE_NAMED:
+    case DBUS_TYPE_CUSTOM:
       {
        int len;
        
        /* Demarshal the string length */
        len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
 
-       *end_pos = pos + len + 1;
+       pos += len + 1;
        
        /* Demarshal the data length */
        len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
@@ -1559,7 +1890,7 @@ demarshal_and_validate_len (const DBusString *str,
   if (!_dbus_string_validate_nul (str, pos,
                                   align_4 - pos))
     {
-      _dbus_verbose ("array length alignment padding not initialized to nul\n");
+      _dbus_verbose ("array length alignment padding not initialized to nul at %d\n", pos);
       return -1;
     }
 
@@ -1574,8 +1905,8 @@ demarshal_and_validate_len (const DBusString *str,
 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
   if (len > MAX_ARRAY_LENGTH)
     {
-      _dbus_verbose ("array length %u exceeds maximum of %u\n",
-                     len, MAX_ARRAY_LENGTH);
+      _dbus_verbose ("array length %u exceeds maximum of %u at pos %d\n",
+                     len, MAX_ARRAY_LENGTH, pos);
       return -1;
     }
   else
@@ -1635,17 +1966,113 @@ _dbus_marshal_validate_type   (const DBusString *str,
 
   data = _dbus_string_get_const_data_len (str, pos, 1);
 
-  if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
+  if (_dbus_type_is_valid (*data))
     {
       *type = *data;
       if (end_pos != NULL)
        *end_pos = pos + 1;
       return TRUE;
     }
+
+  _dbus_verbose ("'%c' %d invalid type code\n", (int) *data, (int) *data);
   
   return FALSE;
 }
 
+/* Faster validator for array data that doesn't call
+ * validate_arg for each value
+ */
+static dbus_bool_t
+validate_array_data (const DBusString *str,
+                     int              byte_order,
+                     int               depth,
+                     int               type,
+                     int               array_type_pos,
+                     int               pos,
+                     int              *new_pos,
+                     int               end)
+{
+  switch (type)
+    {
+    case DBUS_TYPE_INVALID:
+      return FALSE;
+      break;
+
+    case DBUS_TYPE_NIL:
+      break;
+
+    case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_CUSTOM:
+    case DBUS_TYPE_ARRAY:
+    case DBUS_TYPE_DICT:
+      /* This clean recursion to validate_arg is what we
+       * are doing logically for all types, but we don't
+       * really want to call validate_arg for every byte
+       * in a byte array, so the primitive types are
+       * special-cased.
+       */
+      while (pos < end)
+        {
+          if (!_dbus_marshal_validate_arg (str, byte_order, depth,
+                                           type, array_type_pos, pos, &pos))
+            return FALSE;
+        }
+      break;
+      
+    case DBUS_TYPE_BYTE:
+      pos = end;
+      break;
+      
+    case DBUS_TYPE_BOOLEAN:
+      while (pos < end)
+        {
+          unsigned char c;
+          
+          c = _dbus_string_get_byte (str, pos);
+          
+          if (!(c == 0 || c == 1))
+            {
+              _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
+              return FALSE;
+            }
+          
+          ++pos;
+        }
+      break;
+      
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      /* Call validate arg one time to check alignment padding
+       * at start of array
+       */
+      if (!_dbus_marshal_validate_arg (str, byte_order, depth,
+                                       type, array_type_pos, pos, &pos))
+        return FALSE;
+      pos = _DBUS_ALIGN_VALUE (end, 4);
+      break;
+
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+      /* Call validate arg one time to check alignment padding
+       * at start of array
+       */
+      if (!_dbus_marshal_validate_arg (str, byte_order, depth,
+                                       type, array_type_pos, pos, &pos))
+        return FALSE;
+      pos = _DBUS_ALIGN_VALUE (end, 8);
+      break;
+      
+    default:
+      _dbus_verbose ("Unknown message arg type %d\n", type);
+      return FALSE;
+    }
+
+  *new_pos = pos;
+
+  return TRUE;
+}
 
 /** 
  * Validates an argument of a specific type, checking that it
@@ -1655,10 +2082,6 @@ _dbus_marshal_validate_type   (const DBusString *str,
  * returns #TRUE if a valid arg begins at "pos"
  *
  * @todo security: need to audit this function.
- *
- * @todo For array types that can't be invalid, we should not
- * walk the whole array validating it. e.g. just skip all the
- * int values in an int array.
  * 
  * @param str a string
  * @param byte_order the byte order to use
@@ -1726,7 +2149,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
         
        c = _dbus_string_get_byte (str, pos);
 
-       if (c != 0 && c != 1)
+       if (!(c == 0 || c == 1))
          {
            _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
            return FALSE;
@@ -1753,21 +2176,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
       break;
 
     case DBUS_TYPE_INT64:
-    case DBUS_TYPE_UINT64:
-      {
-        int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
-        
-        if (!_dbus_string_validate_nul (str, pos,
-                                        align_8 - pos))
-          {
-            _dbus_verbose ("int64/uint64 alignment padding not initialized to nul\n");
-            return FALSE;
-          }
-
-        *end_pos = align_8 + 8;
-      }
-      break;
-      
+    case DBUS_TYPE_UINT64:      
     case DBUS_TYPE_DOUBLE:
       {
         int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
@@ -1777,7 +2186,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
         if (!_dbus_string_validate_nul (str, pos,
                                         align_8 - pos))
           {
-            _dbus_verbose ("double alignment padding not initialized to nul\n");
+            _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul at %d\n", pos);
             return FALSE;
           }
 
@@ -1785,6 +2194,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
       }
       break;
 
+    case DBUS_TYPE_OBJECT_PATH:
     case DBUS_TYPE_STRING:
       {
        int len;
@@ -1798,10 +2208,16 @@ _dbus_marshal_validate_arg (const DBusString *str,
 
         if (!validate_string (str, pos, len, end_pos))
           return FALSE;
+
+        if (type == DBUS_TYPE_OBJECT_PATH)
+          {
+            if (!_dbus_string_validate_path (str, pos, len))
+              return FALSE;
+          }
       }
       break;
 
-    case DBUS_TYPE_NAMED:
+    case DBUS_TYPE_CUSTOM:
       {
        int len;
 
@@ -1865,7 +2281,10 @@ _dbus_marshal_validate_arg (const DBusString *str,
         
        len = demarshal_and_validate_len (str, byte_order, pos, &pos);
         if (len < 0)
-          return FALSE;
+         {
+           _dbus_verbose ("invalid array length (<0)\n");
+           return FALSE;
+         }
 
         if (len > _dbus_string_get_length (str) - pos)
           {
@@ -1874,12 +2293,13 @@ _dbus_marshal_validate_arg (const DBusString *str,
           }
        
        end = pos + len;
-        
-       while (pos < end)
+
+        if (len > 0 && !validate_array_data (str, byte_order, depth + 1,
+                                            array_type, array_type_pos,
+                                            pos, &pos, end))
          {
-           if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
-                                            array_type, array_type_pos, pos, &pos))
-             return FALSE;
+           _dbus_verbose ("invalid array data\n");
+           return FALSE;
          }
 
         if (pos < end)
@@ -1888,7 +2308,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
              * but the check is here just to be paranoid.
              */
             _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
-                    len, end - pos);
+                           len, end - pos);
             return FALSE;
           }
         
@@ -1936,7 +2356,10 @@ _dbus_marshal_validate_arg (const DBusString *str,
            /* Validate element */
            if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
                                             dict_type, -1, pos, &pos))
-             return FALSE;
+             {
+               _dbus_verbose ("dict arg invalid at offset %d\n", pos);
+               return FALSE;
+             }
          }
        
        if (pos > end)
@@ -1960,6 +2383,35 @@ _dbus_marshal_validate_arg (const DBusString *str,
   return TRUE;
 }
 
+/**
+ * Return #TRUE if the typecode is a valid typecode
+ *
+ * @returns #TRUE if valid
+ */
+dbus_bool_t
+_dbus_type_is_valid (int typecode)
+{
+  switch (typecode)
+    {
+    case DBUS_TYPE_NIL:
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_CUSTOM:
+    case DBUS_TYPE_ARRAY:
+    case DBUS_TYPE_DICT:
+    case DBUS_TYPE_OBJECT_PATH:
+      return TRUE;
+      
+    default:
+      return FALSE;
+    }
+}
 
 /**
  * If in verbose mode, print a block of binary data.
@@ -2072,6 +2524,93 @@ _dbus_verbose_bytes_of_string (const DBusString    *str,
   _dbus_verbose_bytes (d, len);
 }
 
+/**
+ * Marshals a basic type
+ *
+ * @param str string to marshal to
+ * @param type type of value
+ * @param value pointer to value
+ * @param byte_order byte order
+ * @returns #TRUE on success
+ **/
+dbus_bool_t
+_dbus_marshal_basic_type (DBusString *str,
+                         char        type,
+                         void       *value,
+                         int         byte_order)
+{
+  dbus_bool_t retval;
+
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+      retval = _dbus_string_append_byte (str, *(unsigned char *)value);
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      return marshal_4_octets (str, byte_order, *(dbus_uint32_t *)value);
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+      retval = _dbus_marshal_uint64 (str, byte_order, *(dbus_uint64_t *)value);
+      break;
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      retval = _dbus_marshal_double (str, byte_order, *(double *)value);
+      break;
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      retval = FALSE;
+      break;
+    }
+  return retval;
+}
+
+/**
+ * Marshals a basic type array
+ *
+ * @param str string to marshal to
+ * @param element_type type of array elements
+ * @param value pointer to value
+ * @param len length of value data in elements
+ * @param byte_order byte order
+ * @returns #TRUE on success
+ **/
+dbus_bool_t
+_dbus_marshal_basic_type_array (DBusString *str,
+                               char        element_type,
+                               const void *value,
+                               int         len,
+                               int         byte_order)
+{
+  switch (element_type)
+    {
+    case DBUS_TYPE_BOOLEAN:
+      /* FIXME: we canonicalize to 0 or 1 for the single boolean case 
+       * should we here too ? */
+    case DBUS_TYPE_BYTE:
+      return _dbus_marshal_byte_array (str, byte_order, value, len);
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      return marshal_4_octets_array (str, byte_order, value, len);
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      return marshal_8_octets_array (str, byte_order, value, len);
+      break;
+    default:
+      _dbus_assert_not_reached ("non basic type in array");
+      break;
+    }
+  return FALSE;
+}
+
 /** @} */
 
 #ifdef DBUS_BUILD_TESTS
@@ -2086,7 +2625,9 @@ _dbus_marshal_test (void)
   int pos = 0, len;
   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
 #ifdef DBUS_HAVE_INT64
-  dbus_int64_t array3[3] = { 0x123ffffffff, 0x456ffffffff, 0x789ffffffff }, *array4;
+  dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff), 
+                             DBUS_INT64_CONSTANT (0x456ffffffff), 
+                             DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
 #endif
   char *s;
   DBusString t;
@@ -2131,12 +2672,12 @@ _dbus_marshal_test (void)
   /* Marshal signed integers */
   if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
     _dbus_assert_not_reached ("could not marshal signed integer value");
-  if (!_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_INT64_CONSTANT (-0x123456789abc7))
+  if (_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
     _dbus_assert_not_reached ("demarshal failed");
 
   if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
     _dbus_assert_not_reached ("could not marshal signed integer value");
-  if (!_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_INT64_CONSTANT (-0x123456789abc7))
+  if (_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
     _dbus_assert_not_reached ("demarshal failed");
   
   /* Marshal unsigned integers */
@@ -2391,7 +2932,6 @@ _dbus_marshal_test (void)
   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
   _dbus_assert (strcmp (s, "Hello") == 0);
   dbus_free (s);
-
   
   _dbus_string_free (&str);