2005-02-05 Havoc Pennington <hp@redhat.com>
authorHavoc Pennington <hp@redhat.com>
Sun, 6 Feb 2005 04:21:57 +0000 (04:21 +0000)
committerHavoc Pennington <hp@redhat.com>
Sun, 6 Feb 2005 04:21:57 +0000 (04:21 +0000)
* dbus/dbus-message-factory.c (generate_special): more test cases,
increasing coverage

* dbus/dbus-marshal-validate.c (validate_body_helper): return the
reason why a signature was invalid

* dbus/dbus-marshal-header.c (load_and_validate_field): fix to
skip the length of the string before we look at it in validation

* dbus/dbus-string-util.c (_dbus_string_test): add tests for
equal_substring

* dbus/dbus-message.c (_dbus_message_loader_new): default
max_message_length to DBUS_MAXIMUM_MESSAGE_LENGTH

ChangeLog
dbus/dbus-marshal-header.c
dbus/dbus-marshal-validate.c
dbus/dbus-marshal-validate.h
dbus/dbus-message-factory.c
dbus/dbus-message-util.c
dbus/dbus-message.c
dbus/dbus-string-util.c

index 1d35dd0..cbde9ad 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
 2005-02-05  Havoc Pennington  <hp@redhat.com>
 
+       * dbus/dbus-message-factory.c (generate_special): more test cases,
+       increasing coverage
+
+       * dbus/dbus-marshal-validate.c (validate_body_helper): return the
+       reason why a signature was invalid
+
+       * dbus/dbus-marshal-header.c (load_and_validate_field): fix to
+       skip the length of the string before we look at it in validation
+
+       * dbus/dbus-string-util.c (_dbus_string_test): add tests for
+       equal_substring
+
+       * dbus/dbus-message.c (_dbus_message_loader_new): default
+       max_message_length to DBUS_MAXIMUM_MESSAGE_LENGTH
+
+2005-02-05  Havoc Pennington  <hp@redhat.com>
+
        * dbus/dbus-marshal-validate.c (validate_body_helper): fix crash
        if the signature of a variant was empty
        (_dbus_validate_signature_with_reason): catch "(a)" (array inside
index f32e7aa..10d9e20 100644 (file)
@@ -773,6 +773,7 @@ load_and_validate_field (DBusHeader     *header,
   int expected_type;
   const DBusString *value_str;
   int value_pos;
+  int str_data_pos;
   dbus_uint32_t v_UINT32;
   int bad_string_code;
   dbus_bool_t (* string_validation_func) (const DBusString *str,
@@ -812,6 +813,7 @@ load_and_validate_field (DBusHeader     *header,
   v_UINT32 = 0;
   value_str = NULL;
   value_pos = -1;
+  str_data_pos = -1;
   bad_string_code = DBUS_VALID;
 
   if (expected_type == DBUS_TYPE_UINT32)
@@ -825,6 +827,7 @@ load_and_validate_field (DBusHeader     *header,
     {
       _dbus_header_get_field_raw (header, field,
                                   &value_str, &value_pos);
+      str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4;
     }
   else
     {
@@ -844,7 +847,7 @@ load_and_validate_field (DBusHeader     *header,
       if (_dbus_string_equal_substring (&_dbus_local_interface_str,
                                         0,
                                         _dbus_string_get_length (&_dbus_local_interface_str),
-                                        value_str, value_pos))
+                                        value_str, str_data_pos))
         {
           _dbus_verbose ("Message is on the local interface\n");
           return DBUS_INVALID_USES_LOCAL_INTERFACE;
@@ -870,13 +873,10 @@ load_and_validate_field (DBusHeader     *header,
       /* OBJECT_PATH was validated generically due to its type */
       string_validation_func = NULL;
 
-      _dbus_verbose ("value_str %p value_pos %d value_str_len %d\n",
-                     value_str, value_pos,
-                     _dbus_string_get_length (value_str));
       if (_dbus_string_equal_substring (&_dbus_local_path_str,
                                         0,
                                         _dbus_string_get_length (&_dbus_local_path_str),
-                                        value_str, value_pos))
+                                        value_str, str_data_pos))
         {
           _dbus_verbose ("Message is from the local path\n");
           return DBUS_INVALID_USES_LOCAL_PATH;
@@ -910,7 +910,11 @@ load_and_validate_field (DBusHeader     *header,
       len = _dbus_marshal_read_uint32 (value_str, value_pos,
                                        header->byte_order, NULL);
 
-      if (!(*string_validation_func) (value_str, value_pos + 4, len))
+#if 0
+      _dbus_verbose ("Validating string header field; code %d if fails\n",
+                     bad_string_code);
+#endif
+      if (!(*string_validation_func) (value_str, str_data_pos, len))
         return bad_string_code;
     }
 
index f7b46c0..c1d9582 100644 (file)
@@ -335,6 +335,7 @@ validate_body_helper (DBusTypeReader       *reader,
           {
             dbus_uint32_t claimed_len;
             DBusString str;
+            DBusValidity validity;
 
             claimed_len = *p;
             ++p;
@@ -344,9 +345,12 @@ validate_body_helper (DBusTypeReader       *reader,
               return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
 
             _dbus_string_init_const_len (&str, p, claimed_len);
-            if (!_dbus_validate_signature (&str, 0,
-                                           _dbus_string_get_length (&str)))
-              return DBUS_INVALID_BAD_SIGNATURE;
+            validity =
+              _dbus_validate_signature_with_reason (&str, 0,
+                                                    _dbus_string_get_length (&str));
+
+            if (validity != DBUS_VALID)
+              return validity;
 
             p += claimed_len;
 
@@ -389,7 +393,7 @@ validate_body_helper (DBusTypeReader       *reader,
               return DBUS_INVALID_VARIANT_SIGNATURE_BAD;
 
             p += claimed_len;
-
+            
             if (*p != DBUS_TYPE_INVALID)
               return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL;
             ++p;
index 55739d3..8989d50 100644 (file)
@@ -48,6 +48,7 @@ typedef enum
  */
 typedef enum
 {
+#define _DBUS_NEGATIVE_VALIDITY_COUNT 3
   DBUS_INVALID_FOR_UNKNOWN_REASON = -3,
   DBUS_VALID_BUT_INCOMPLETE = -2,
   DBUS_VALIDITY_UNKNOWN = -1,
@@ -91,23 +92,23 @@ typedef enum
   DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM = 37,
   DBUS_INVALID_BAD_PATH = 38,
   DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS = 39,
-  DBUS_INVALID_BAD_SIGNATURE = 40,
-  DBUS_INVALID_BAD_UTF8_IN_STRING = 41,
-  DBUS_INVALID_ARRAY_LENGTH_INCORRECT = 42,
-  DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS = 43,
-  DBUS_INVALID_VARIANT_SIGNATURE_BAD = 44,
-  DBUS_INVALID_VARIANT_SIGNATURE_EMPTY = 45,
-  DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES = 46,
-  DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL = 47,
-  DBUS_INVALID_STRING_MISSING_NUL = 48,
-  DBUS_INVALID_SIGNATURE_MISSING_NUL = 49,
-  DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION = 50,
-  DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED = 51,
-  DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED = 52,
-  DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS = 53,
-  DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD = 54,
-  DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS = 55,
-  DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY = 56
+  DBUS_INVALID_BAD_UTF8_IN_STRING = 40,
+  DBUS_INVALID_ARRAY_LENGTH_INCORRECT = 41,
+  DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS = 42,
+  DBUS_INVALID_VARIANT_SIGNATURE_BAD = 43,
+  DBUS_INVALID_VARIANT_SIGNATURE_EMPTY = 44,
+  DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES = 45,
+  DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL = 46,
+  DBUS_INVALID_STRING_MISSING_NUL = 47,
+  DBUS_INVALID_SIGNATURE_MISSING_NUL = 48,
+  DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION = 49,
+  DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED = 50,
+  DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED = 51,
+  DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS = 52,
+  DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD = 53,
+  DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS = 54,
+  DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY = 55,
+  DBUS_VALIDITY_LAST
 } DBusValidity;
 
 DBusValidity _dbus_validate_signature_with_reason (const DBusString *type_str,
index 2610981..adcb9b2 100644 (file)
@@ -35,7 +35,9 @@ typedef enum
   } ChangeType;
 
 #define BYTE_ORDER_OFFSET  0
+#define TYPE_OFFSET        1
 #define BODY_LENGTH_OFFSET 4
+#define FIELDS_ARRAY_LENGTH_OFFSET 12
 
 static void
 iter_recurse (DBusMessageDataIter *iter)
@@ -165,11 +167,12 @@ generate_many_bodies_inner (DBusMessageDataIter *iter,
   DBusMessage *message;
   DBusString signature;
   DBusString body;
-  
-  message = dbus_message_new_method_call ("org.freedesktop.Foo",
+
+  /* Keeping this small makes things go faster */
+  message = dbus_message_new_method_call ("o.z.F",
                                           "/",
-                                          "org.freedesktop.Blah",
-                                          "NahNahNah");
+                                          "o.z.B",
+                                          "Nah");
   if (message == NULL)
     _dbus_assert_not_reached ("oom");
 
@@ -212,6 +215,26 @@ generate_many_bodies_inner (DBusMessageDataIter *iter,
   return *message_p != NULL;
 }
 
+static void
+generate_from_message (DBusString            *data,
+                       DBusValidity          *expected_validity,
+                       DBusMessage           *message)
+{
+  _dbus_message_set_serial (message, 1);
+  _dbus_message_lock (message);
+
+  *expected_validity = DBUS_VALID;
+  
+  /* move for efficiency, since we'll nuke the message anyway */
+  if (!_dbus_string_move (&message->header.data, 0,
+                          data, 0))
+    _dbus_assert_not_reached ("oom");
+
+  if (!_dbus_string_copy (&message->body, 0,
+                          data, _dbus_string_get_length (data)))
+    _dbus_assert_not_reached ("oom");
+}
+
 static dbus_bool_t
 generate_outer (DBusMessageDataIter   *iter,
                 DBusString            *data,
@@ -228,19 +251,7 @@ generate_outer (DBusMessageDataIter   *iter,
   
   _dbus_assert (message != NULL);
 
-  _dbus_message_set_serial (message, 1);
-  _dbus_message_lock (message);
-  
-  *expected_validity = DBUS_VALID;
-
-  /* move for efficiency, since we'll nuke the message anyway */
-  if (!_dbus_string_move (&message->header.data, 0,
-                          data, 0))
-    _dbus_assert_not_reached ("oom");
-
-  if (!_dbus_string_copy (&message->body, 0,
-                          data, _dbus_string_get_length (data)))
-    _dbus_assert_not_reached ("oom");
+  generate_from_message (data, expected_validity, message);
 
   dbus_message_unref (message);
 
@@ -265,6 +276,334 @@ generate_many_bodies (DBusMessageDataIter   *iter,
                          generate_many_bodies_inner);
 }
 
+static DBusMessage*
+simple_method_call (void)
+{
+  DBusMessage *message;
+  /* Keeping this small makes stuff go faster */
+  message = dbus_message_new_method_call ("o.b.Q",
+                                          "/f/b",
+                                          "o.b.Z",
+                                          "Fro");
+  if (message == NULL)
+    _dbus_assert_not_reached ("oom");
+  return message;
+}
+
+static DBusMessage*
+simple_signal (void)
+{
+  DBusMessage *message;
+  message = dbus_message_new_signal ("/f/b",
+                                     "o.b.Z",
+                                     "Fro");
+  if (message == NULL)
+    _dbus_assert_not_reached ("oom");
+  return message;
+}
+
+static DBusMessage*
+simple_method_return (void)
+{
+  DBusMessage *message;
+  message =  dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
+  if (message == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  set_reply_serial (message);
+  
+  return message;
+}
+
+static dbus_bool_t
+generate_special (DBusMessageDataIter   *iter,
+                  DBusString            *data,
+                  DBusValidity          *expected_validity)
+{
+  int item_seq;
+  DBusMessage *message;
+  int pos;
+  dbus_int32_t v_INT32;
+
+  _dbus_assert (_dbus_string_get_length (data) == 0);
+  
+  message = NULL;
+  pos = -1;
+  v_INT32 = 42;
+  item_seq = iter_get_sequence (iter);
+
+  if (item_seq == 0)
+    {
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+                                     
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      /* set an invalid typecode */
+      _dbus_string_set_byte (data, pos + 1, '$');
+
+      *expected_validity = DBUS_INVALID_UNKNOWN_TYPECODE;
+    }
+  else if (item_seq == 1)
+    {
+      char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH+1];
+      const char *v_STRING;
+      int i;
+      
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+
+      i = 0;
+      while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1))
+        {
+          long_sig[i] = DBUS_TYPE_ARRAY;
+          ++i;
+        }
+
+      v_STRING = long_sig;
+      if (!_dbus_header_set_field_basic (&message->header,
+                                         DBUS_HEADER_FIELD_SIGNATURE,
+                                         DBUS_TYPE_SIGNATURE,
+                                         &v_STRING))
+        _dbus_assert_not_reached ("oom");
+      
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION;
+    }
+  else if (item_seq == 2)
+    {
+      char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2+3];
+      const char *v_STRING;
+      int i;
+      
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+
+      i = 0;
+      while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1))
+        {
+          long_sig[i] = DBUS_STRUCT_BEGIN_CHAR;
+          ++i;
+        }
+
+      long_sig[i] = DBUS_TYPE_INT32;
+      ++i;
+
+      while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2 + 3))
+        {
+          long_sig[i] = DBUS_STRUCT_END_CHAR;
+          ++i;
+        }
+      
+      v_STRING = long_sig;
+      if (!_dbus_header_set_field_basic (&message->header,
+                                         DBUS_HEADER_FIELD_SIGNATURE,
+                                         DBUS_TYPE_SIGNATURE,
+                                         &v_STRING))
+        _dbus_assert_not_reached ("oom");
+      
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION;
+    }
+  else if (item_seq == 3)
+    {
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+                                     
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR);
+      
+      *expected_validity = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
+    }
+  else if (item_seq == 4)
+    {
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+                                     
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_END_CHAR);
+      
+      *expected_validity = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
+    }
+  else if (item_seq == 5)
+    {
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+                                     
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR);
+      _dbus_string_set_byte (data, pos + 2, DBUS_STRUCT_END_CHAR);
+      
+      *expected_validity = DBUS_INVALID_STRUCT_HAS_NO_FIELDS;
+    }
+  else if (item_seq == 6)
+    {
+      message = simple_method_call ();
+      generate_from_message (data, expected_validity, message);
+      
+      _dbus_string_set_byte (data, TYPE_OFFSET, DBUS_MESSAGE_TYPE_INVALID);
+      
+      *expected_validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
+    }
+  else if (item_seq == 7)
+    {
+      /* Messages of unknown type are considered valid */
+      message = simple_method_call ();
+      generate_from_message (data, expected_validity, message);
+      
+      _dbus_string_set_byte (data, TYPE_OFFSET, 100);
+      
+      *expected_validity = DBUS_VALID;
+    }
+  else if (item_seq == 8)
+    {
+      message = simple_method_call ();
+      generate_from_message (data, expected_validity, message);
+      
+      _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET,
+                                DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4,
+                                message->byte_order);
+      _dbus_marshal_set_uint32 (data, FIELDS_ARRAY_LENGTH_OFFSET,
+                                DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4,
+                                message->byte_order);
+      *expected_validity = DBUS_INVALID_MESSAGE_TOO_LONG;
+    }
+  else if (item_seq == 9)
+    {
+      const char *v_STRING = "not a valid bus name";
+      message = simple_method_call ();
+
+      if (!_dbus_header_set_field_basic (&message->header,
+                                         DBUS_HEADER_FIELD_SENDER,
+                                         DBUS_TYPE_STRING, &v_STRING))
+        _dbus_assert_not_reached ("oom");
+      
+      generate_from_message (data, expected_validity, message);
+
+      *expected_validity = DBUS_INVALID_BAD_SENDER;
+    }
+  else if (item_seq == 10)
+    {
+      message = simple_method_call ();
+
+      if (!dbus_message_set_interface (message, DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL))
+        _dbus_assert_not_reached ("oom");
+      
+      generate_from_message (data, expected_validity, message);
+
+      *expected_validity = DBUS_INVALID_USES_LOCAL_INTERFACE;
+    }
+  else if (item_seq == 11)
+    {
+      message = simple_method_call ();
+
+      if (!dbus_message_set_path (message, DBUS_PATH_ORG_FREEDESKTOP_LOCAL))
+        _dbus_assert_not_reached ("oom");
+      
+      generate_from_message (data, expected_validity, message);
+
+      *expected_validity = DBUS_INVALID_USES_LOCAL_PATH;
+    }
+  else if (item_seq == 12)
+    {
+      /* Method calls don't have to have interface */
+      message = simple_method_call ();
+
+      if (!dbus_message_set_interface (message, NULL))
+        _dbus_assert_not_reached ("oom");
+      
+      generate_from_message (data, expected_validity, message);
+      
+      *expected_validity = DBUS_VALID;
+    }
+  else if (item_seq == 13)
+    {
+      /* Signals require an interface */
+      message = simple_signal ();
+
+      if (!dbus_message_set_interface (message, NULL))
+        _dbus_assert_not_reached ("oom");
+      
+      generate_from_message (data, expected_validity, message);
+      
+      *expected_validity = DBUS_INVALID_MISSING_INTERFACE;
+    }
+  else if (item_seq == 14)
+    {
+      message = simple_method_return ();
+
+      if (!_dbus_header_delete_field (&message->header, DBUS_HEADER_FIELD_REPLY_SERIAL))
+        _dbus_assert_not_reached ("oom");
+      
+      generate_from_message (data, expected_validity, message);
+      
+      *expected_validity = DBUS_INVALID_MISSING_REPLY_SERIAL;
+    }
+  else
+    {
+      return FALSE;
+    }
+
+  if (message)
+    dbus_message_unref (message);
+
+  iter_next (iter);
+  return TRUE;
+}
+
 static dbus_bool_t
 generate_wrong_length (DBusMessageDataIter *iter,
                        DBusString          *data,
@@ -388,6 +727,145 @@ generate_byte_changed (DBusMessageDataIter *iter,
   return TRUE;
 }
 
+static dbus_bool_t
+find_next_typecode (DBusMessageDataIter *iter,
+                    DBusString          *data,
+                    DBusValidity        *expected_validity)
+{
+  int body_seq;
+  int byte_seq;
+  int base_depth;
+
+  base_depth = iter->depth;
+
+ restart:
+  _dbus_assert (iter->depth == (base_depth + 0));
+  _dbus_string_set_length (data, 0);
+
+  body_seq = iter_get_sequence (iter);
+  
+  if (!generate_many_bodies (iter, data, expected_validity))
+    return FALSE;
+  /* Undo the "next" in generate_many_bodies */
+  iter_set_sequence (iter, body_seq);
+  
+  iter_recurse (iter);
+  while (TRUE)
+    {
+      _dbus_assert (iter->depth == (base_depth + 1));
+      
+      byte_seq = iter_get_sequence (iter);
+
+      _dbus_assert (byte_seq <= _dbus_string_get_length (data));
+      
+      if (byte_seq == _dbus_string_get_length (data))
+        {
+          /* reset byte count */
+          iter_set_sequence (iter, 0);
+          iter_unrecurse (iter);
+          _dbus_assert (iter->depth == (base_depth + 0));
+          iter_next (iter); /* go to the next body */
+          goto restart;
+        }
+
+      _dbus_assert (byte_seq < _dbus_string_get_length (data));
+
+      if (_dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq)))
+        break;
+      else
+        iter_next (iter);
+    }
+
+  _dbus_assert (byte_seq == iter_get_sequence (iter));
+  _dbus_assert (byte_seq < _dbus_string_get_length (data));
+
+  iter_unrecurse (iter);
+
+  _dbus_assert (iter->depth == (base_depth + 0));
+  
+  return TRUE;
+}
+
+static const int typecodes[] = {
+  DBUS_TYPE_INVALID,
+  DBUS_TYPE_BYTE,
+  DBUS_TYPE_BOOLEAN,
+  DBUS_TYPE_INT16,
+  DBUS_TYPE_UINT16,
+  DBUS_TYPE_INT32,
+  DBUS_TYPE_UINT32,
+  DBUS_TYPE_INT64,
+  DBUS_TYPE_UINT64,
+  DBUS_TYPE_DOUBLE,
+  DBUS_TYPE_STRING,
+  DBUS_TYPE_OBJECT_PATH,
+  DBUS_TYPE_SIGNATURE,
+  DBUS_TYPE_ARRAY,
+  DBUS_TYPE_VARIANT,
+  DBUS_STRUCT_BEGIN_CHAR,
+  DBUS_STRUCT_END_CHAR,
+  DBUS_DICT_ENTRY_BEGIN_CHAR,
+  DBUS_DICT_ENTRY_END_CHAR,
+  255 /* random invalid typecode */
+};
+  
+static dbus_bool_t
+generate_typecode_changed (DBusMessageDataIter *iter,
+                           DBusString          *data,
+                           DBusValidity        *expected_validity)
+{
+  int byte_seq;
+  int typecode_seq;
+  int base_depth;
+
+  base_depth = iter->depth;
+
+ restart:
+  _dbus_assert (iter->depth == (base_depth + 0));
+  _dbus_string_set_length (data, 0);
+  
+  if (!find_next_typecode (iter, data, expected_validity))
+    return FALSE;
+
+  iter_recurse (iter);
+  byte_seq = iter_get_sequence (iter);
+
+  _dbus_assert (byte_seq < _dbus_string_get_length (data));
+  
+  iter_recurse (iter);
+  typecode_seq = iter_get_sequence (iter);
+  iter_next (iter);
+
+  _dbus_assert (typecode_seq <= _DBUS_N_ELEMENTS (typecodes));
+  
+  if (typecode_seq == _DBUS_N_ELEMENTS (typecodes))
+    {
+      _dbus_assert (iter->depth == (base_depth + 2));
+      iter_set_sequence (iter, 0); /* reset typecode sequence */
+      iter_unrecurse (iter);
+      _dbus_assert (iter->depth == (base_depth + 1));
+      iter_next (iter); /* go to the next byte_seq */
+      iter_unrecurse (iter);
+      _dbus_assert (iter->depth == (base_depth + 0));
+      goto restart;
+    }
+
+  _dbus_assert (iter->depth == (base_depth + 2));
+  iter_unrecurse (iter);
+  _dbus_assert (iter->depth == (base_depth + 1));
+  iter_unrecurse (iter);
+  _dbus_assert (iter->depth == (base_depth + 0));
+
+#if 0
+  printf ("Changing byte %d in message %d to %c\n",
+          byte_seq, iter_get_sequence (iter), typecodes[typecode_seq]);
+#endif
+  
+  _dbus_string_set_byte (data, byte_seq, typecodes[typecode_seq]);
+  *expected_validity = DBUS_VALIDITY_UNKNOWN;
+  return TRUE;
+}
+
 typedef struct
 {
   ChangeType type;
@@ -528,9 +1006,14 @@ typedef struct
 static const DBusMessageGenerator generators[] = {
   { "trivial example of each message type", generate_trivial },
   { "assorted arguments", generate_many_bodies },
+  { "assorted special cases", generate_special },
   { "each uint32 modified", generate_uint32_changed },
   { "wrong body lengths", generate_wrong_length },
-  { "each byte modified", generate_byte_changed }
+  { "each byte modified", generate_byte_changed },
+#if 0
+  /* This is really expensive and doesn't add too much coverage */
+  { "change each typecode", generate_typecode_changed }
+#endif
 };
 
 void
index c646ebf..69db201 100644 (file)
@@ -78,6 +78,45 @@ dbus_message_iter_get_args (DBusMessageIter *iter,
 #include <stdio.h>
 #include <stdlib.h>
 
+static int validities_seen[DBUS_VALIDITY_LAST + _DBUS_NEGATIVE_VALIDITY_COUNT];
+
+static void
+reset_validities_seen (void)
+{
+  int i;
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (validities_seen))
+    {
+      validities_seen[i] = 0;
+      ++i;
+    }
+}
+
+static void
+record_validity_seen (DBusValidity validity)
+{
+  validities_seen[validity + _DBUS_NEGATIVE_VALIDITY_COUNT] += 1;
+}
+
+static void
+print_validities_seen (dbus_bool_t not_seen)
+{
+  int i;
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (validities_seen))
+    {
+      if ((i - _DBUS_NEGATIVE_VALIDITY_COUNT) == DBUS_VALIDITY_UNKNOWN ||
+          (i - _DBUS_NEGATIVE_VALIDITY_COUNT) == DBUS_INVALID_FOR_UNKNOWN_REASON)
+        ;
+      else if ((not_seen && validities_seen[i] == 0) ||
+               (!not_seen && validities_seen[i] > 0))
+        printf ("validity %3d seen %d times\n",
+                i - _DBUS_NEGATIVE_VALIDITY_COUNT,
+                validities_seen[i]);
+      ++i;
+    }
+}
+
 static void
 check_memleaks (void)
 {
@@ -130,6 +169,8 @@ check_have_valid_message (DBusMessageLoader *loader)
     goto failed;
 #endif
 
+  record_validity_seen (DBUS_VALID);
+  
   retval = TRUE;
 
  failed:
@@ -153,6 +194,8 @@ check_invalid_message (DBusMessageLoader *loader,
       goto failed;
     }
 
+  record_validity_seen (loader->corruption_reason);
+  
   if (expected_validity != DBUS_INVALID_FOR_UNKNOWN_REASON &&
       loader->corruption_reason != expected_validity)
     {
@@ -190,6 +233,7 @@ check_incomplete_message (DBusMessageLoader *loader)
       goto failed;
     }
 
+  record_validity_seen (DBUS_VALID_BUT_INCOMPLETE);
   retval = TRUE;
 
  failed:
@@ -212,8 +256,12 @@ check_loader_results (DBusMessageLoader      *loader,
   else if (expected_validity == DBUS_VALIDITY_UNKNOWN)
     {
       /* here we just know we didn't segfault and that was the
-       * only test
+       * only test. Also, we record that we got coverage
+       * for the validity reason.
        */
+      if (_dbus_message_loader_get_is_corrupted (loader))
+        record_validity_seen (loader->corruption_reason);
+      
       return TRUE;
     }
   else
@@ -1170,6 +1218,8 @@ _dbus_message_test (const char *test_data_dir)
     DBusMessageData mdata;
     int count;
 
+    reset_validities_seen ();
+    
     count = 0;
     _dbus_message_data_iter_init (&diter);
     
@@ -1190,6 +1240,9 @@ _dbus_message_test (const char *test_data_dir)
       }
 
     printf ("%d sample messages tested\n", count);
+
+    print_validities_seen (FALSE);
+    print_validities_seen (TRUE);
   }
   
   check_memleaks ();
index 46a30b6..a285255 100644 (file)
@@ -2957,11 +2957,9 @@ _dbus_message_loader_new (void)
 
   loader->corrupted = FALSE;
   loader->corruption_reason = DBUS_VALID;
-  
-  /* Try to cap message size at something that won't *totally* hose
-   * the system if we have a couple of them.
-   */
-  loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
+
+  /* this can be configured by the app, but defaults to the protocol max */
+  loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
 
   if (!_dbus_string_init (&loader->data))
     {
index 1ff2ec6..0610c66 100644 (file)
@@ -377,6 +377,49 @@ _dbus_string_test (void)
       ++i;
     }
 
+  /* Test equality */
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("oom");
+
+  if (!_dbus_string_append (&str, "Hello World"))
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_string_init_const (&other, "H");
+  _dbus_assert (_dbus_string_equal_substring (&str, 0, 1, &other, 0));
+  _dbus_assert (_dbus_string_equal_substring (&str, 1, 0, &other, 1));
+  _dbus_string_init_const (&other, "Hello");
+  _dbus_assert (_dbus_string_equal_substring (&str, 0, 5, &other, 0));
+  _dbus_assert (_dbus_string_equal_substring (&str, 1, 4, &other, 1));
+  _dbus_assert (_dbus_string_equal_substring (&str, 2, 3, &other, 2));
+  _dbus_assert (_dbus_string_equal_substring (&str, 3, 2, &other, 3));
+  _dbus_assert (_dbus_string_equal_substring (&str, 4, 1, &other, 4));
+  _dbus_assert (_dbus_string_equal_substring (&str, 5, 0, &other, 5));
+
+  _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 0));
+  _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 1));
+  _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 2));
+  _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 3));
+  _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 4));
+  _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 5));
+
+  
+  _dbus_string_init_const (&other, "World");
+  _dbus_assert (_dbus_string_equal_substring (&str, 6,  5, &other, 0));
+  _dbus_assert (_dbus_string_equal_substring (&str, 7,  4, &other, 1));
+  _dbus_assert (_dbus_string_equal_substring (&str, 8,  3, &other, 2));
+  _dbus_assert (_dbus_string_equal_substring (&str, 9,  2, &other, 3));
+  _dbus_assert (_dbus_string_equal_substring (&str, 10, 1, &other, 4));
+  _dbus_assert (_dbus_string_equal_substring (&str, 11, 0, &other, 5));
+
+  _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 6));
+  _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 7));
+  _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 8));
+  _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 9));
+  _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 10));
+  _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 11));
+  
+  _dbus_string_free (&str);
+  
   /* Test appending data */
   if (!_dbus_string_init (&str))
     _dbus_assert_not_reached ("failed to init string");