Validate arg0namespace matches' values.
authorWill Thompson <will.thompson@collabora.co.uk>
Sun, 21 Nov 2010 16:34:51 +0000 (16:34 +0000)
committerWill Thompson <will.thompson@collabora.co.uk>
Tue, 23 Nov 2010 10:57:22 +0000 (10:57 +0000)
I could be convinced that this is overkill, but it seems sensible to
forbid obviously-broken arg0namespace matches.

bus/signals.c
dbus/dbus-marshal-validate.c
dbus/dbus-marshal-validate.h

index 9939a23..daf8540 100644 (file)
@@ -771,7 +771,22 @@ bus_match_rule_parse_arg_match (BusMatchRule     *rule,
         }
       else if (_dbus_string_equal_c_str (&key_str, "arg0namespace"))
         {
+          int value_len = _dbus_string_get_length (value);
+
           is_namespace = TRUE;
+
+          if (value_len > 0 &&
+              _dbus_string_get_byte (value, value_len - 1) == '.')
+            value_len--;
+
+          if (!_dbus_validate_bus_namespace (value, 0, value_len))
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                  "arg0namespace='%s' is not a valid (optionally "
+                  "period-terminated) prefix of a bus name",
+                  _dbus_string_get_const_data (value));
+              goto failed;
+            }
         }
       else
         {
@@ -2109,9 +2124,62 @@ test_parsing (void *data)
       bus_match_rule_unref (rule);
     }
 
+  rule = check_parse (TRUE, "arg0namespace='foo.'");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags == BUS_MATCH_ARGS);
+      _dbus_assert (rule->args != NULL);
+      _dbus_assert (rule->args_len == 1);
+      _dbus_assert (strcmp (rule->args[0], "foo.") == 0);
+      _dbus_assert ((rule->arg_lens[0] & BUS_MATCH_ARG_NAMESPACE)
+          == BUS_MATCH_ARG_NAMESPACE);
+
+      bus_match_rule_unref (rule);
+    }
+
+  rule = check_parse (TRUE, "arg0namespace='foo.bar'");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags == BUS_MATCH_ARGS);
+      _dbus_assert (rule->args != NULL);
+      _dbus_assert (rule->args_len == 1);
+      _dbus_assert (strcmp (rule->args[0], "foo.bar") == 0);
+      _dbus_assert ((rule->arg_lens[0] & BUS_MATCH_ARG_NAMESPACE)
+          == BUS_MATCH_ARG_NAMESPACE);
+
+      bus_match_rule_unref (rule);
+    }
+
+  rule = check_parse (TRUE, "arg0namespace='foo.bar.'");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags == BUS_MATCH_ARGS);
+      _dbus_assert (rule->args != NULL);
+      _dbus_assert (rule->args_len == 1);
+      _dbus_assert (strcmp (rule->args[0], "foo.bar.") == 0);
+      _dbus_assert ((rule->arg_lens[0] & BUS_MATCH_ARG_NAMESPACE)
+          == BUS_MATCH_ARG_NAMESPACE);
+
+      bus_match_rule_unref (rule);
+    }
+
+  /* Only arg0namespace is supported. */
   rule = check_parse (FALSE, "arg1namespace='foo'");
   _dbus_assert (rule == NULL);
 
+  /* An empty string isn't a valid namespace prefix (you should just not
+   * specify this key at all).
+   */
+  rule = check_parse (FALSE, "arg0namespace=''");
+  _dbus_assert (rule == NULL);
+
+  /* Two trailing periods on otherwise-valid namespaces aren't allowed. */
+  rule = check_parse (FALSE, "arg0namespace='foo..'");
+  _dbus_assert (rule == NULL);
+
+  rule = check_parse (FALSE, "arg0namespace='foo.bar..'");
+  _dbus_assert (rule == NULL);
+
   /* Too-large argN */
   rule = check_parse (FALSE, "arg300='foo'");
   _dbus_assert (rule == NULL);
index aa470fc..7d49624 100644 (file)
@@ -1062,23 +1062,11 @@ _dbus_validate_error_name (const DBusString  *str,
     ((c) >= 'a' && (c) <= 'z') ||               \
     ((c) == '_') || ((c) == '-'))
 
-/**
- * Checks that the given range of the string is a valid bus name in
- * the D-Bus protocol. This includes a length restriction, etc., see
- * the specification.
- *
- * @todo this is inconsistent with most of DBusString in that
- * it allows a start,len range that extends past the string end.
- *
- * @param str the string
- * @param start first byte index to check
- * @param len number of bytes to check
- * @returns #TRUE if the byte range exists and is a valid name
- */
-dbus_bool_t
-_dbus_validate_bus_name (const DBusString  *str,
-                         int                start,
-                         int                len)
+static dbus_bool_t
+_dbus_validate_bus_name_full (const DBusString  *str,
+                              int                start,
+                              int                len,
+                              dbus_bool_t        is_namespace)
 {
   const unsigned char *s;
   const unsigned char *end;
@@ -1156,13 +1144,55 @@ _dbus_validate_bus_name (const DBusString  *str,
       ++s;
     }
 
-  if (_DBUS_UNLIKELY (last_dot == NULL))
+  if (!is_namespace && _DBUS_UNLIKELY (last_dot == NULL))
     return FALSE;
 
   return TRUE;
 }
 
 /**
+ * Checks that the given range of the string is a valid bus name in
+ * the D-Bus protocol. This includes a length restriction, etc., see
+ * the specification.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_validate_bus_name (const DBusString  *str,
+                         int                start,
+                         int                len)
+{
+  return _dbus_validate_bus_name_full (str, start, len, FALSE);
+}
+
+/**
+ * Checks that the given range of the string is a prefix of a valid bus name in
+ * the D-Bus protocol. Unlike _dbus_validate_bus_name(), this accepts strings
+ * with only one period-separated component.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_validate_bus_namespace (const DBusString  *str,
+                              int                start,
+                              int                len)
+{
+  return _dbus_validate_bus_name_full (str, start, len, TRUE);
+}
+
+/**
  * Checks that the given range of the string is a valid message type
  * signature in the D-Bus protocol.
  *
index 5817de3..9b89608 100644 (file)
@@ -143,6 +143,9 @@ dbus_bool_t _dbus_validate_error_name (const DBusString *str,
 dbus_bool_t _dbus_validate_bus_name   (const DBusString *str,
                                        int               start,
                                        int               len);
+dbus_bool_t _dbus_validate_bus_namespace (const DBusString  *str,
+                                          int                start,
+                                          int                len);
 dbus_bool_t _dbus_validate_signature  (const DBusString *str,
                                        int               start,
                                        int               len);