dbus/dbus dbus-bus.c,1.26,1.27 dbus-connection.c,1.71,1.72 dbus-internals.c,1.33,1.34 dbus-internals.h,1.38,1.39 dbus-marshal.c,1.44,1.45 dbus-message-builder.c,1.19,1.20 dbus-message.c,1.110,1.111 dbus-message.h,1.46,1.47 dbus-protocol.h,1.23,1.24 dbus-string.c,1.42,1.43 dbus-string.h,1.21,1.22
Havoc Pennington
hp@pdx.freedesktop.org
Mon, 20 Oct 2003 22:46:54 -0700
Update of /cvs/dbus/dbus/dbus
In directory pdx:/tmp/cvs-serv23383/dbus
Modified Files:
dbus-bus.c dbus-connection.c dbus-internals.c dbus-internals.h
dbus-marshal.c dbus-message-builder.c dbus-message.c
dbus-message.h dbus-protocol.h dbus-string.c dbus-string.h
Log Message:
2003-10-20 Havoc Pennington <hp@redhat.com>
hmm, make check is currently not passing.
* doc/dbus-specification.xml: add requirement that custom type
names follow the same rules as interface names.
* dbus/dbus-protocol.h: change some of the byte codes, to avoid
duplication and allow 'c' to be 'custom'; dict is now 'm' for
'map'
* doc/dbus-specification.xml: update type codes to match
dbus-protocol.h, using the ASCII byte values. Rename type NAMED to
CUSTOM. Add type OBJECT_PATH to the spec.
2003-10-17 Havoc Pennington <hp@redhat.com>
* bus/driver.c (create_unique_client_name): use "." as separator
in base service names instead of '-'
* dbus/dbus-string.c (_dbus_string_get_byte): allow getting nul
byte at the end of the string
* dbus/dbus-internals.h (_DBUS_LIKELY, _DBUS_UNLIKELY): add
optimization macros since string validation seems to be a slow
point.
* doc/dbus-specification.xml: restrict valid
service/interface/member/error names. Add test suite code for the
name validation.
* dbus/dbus-string.c: limit service/interface/member/error names
to [0-9][A-Z][a-z]_
* dbus/dbus-connection.c (dbus_connection_dispatch): add missing
format arg to verbose spew
* glib/dbus-gproxy.c (dbus_gproxy_call_no_reply): if not out of
memory, return instead of g_error
* test/test-service.c (path_message_func): support emitting a
signal on request
* dbus/dbus-bus.c (init_connections_unlocked): only fill in
activation bus type if DBUS_BUS_ACTIVATION was set; default to
assuming the activation bus was the session bus so that services
started manually will still register.
(init_connections_unlocked): fix so that in OOM situation we get
the same semantics when retrying the function
* test/test-service.c (main): change to use path registration, to
test those codepaths; register with DBUS_BUS_ACTIVATION rather
than DBUS_BUS_SESSION
Index: dbus-bus.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-bus.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- dbus-bus.c 16 Oct 2003 06:34:51 -0000 1.26
+++ dbus-bus.c 21 Oct 2003 05:46:51 -0000 1.27
@@ -139,6 +139,9 @@
/* Don't init these twice, we may run this code twice if
* init_connections_unlocked() fails midway through.
+ * In practice, each block below should contain only one
+ * "return FALSE" or running through twice may not
+ * work right.
*/
if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
@@ -148,22 +151,23 @@
if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SYSTEM],
"DBUS_SYSTEM_BUS_ADDRESS"))
return FALSE;
-
- if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
- {
- /* Use default system bus address if none set in environment */
- bus_connection_addresses[DBUS_BUS_SYSTEM] =
- _dbus_strdup (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS);
- if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
- return FALSE;
+ }
- _dbus_verbose (" used default system bus \"%s\"\n",
- bus_connection_addresses[DBUS_BUS_SYSTEM]);
- }
- else
- _dbus_verbose (" used env var system bus \"%s\"\n",
- bus_connection_addresses[DBUS_BUS_SYSTEM]);
+
+ if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
+ {
+ /* Use default system bus address if none set in environment */
+ bus_connection_addresses[DBUS_BUS_SYSTEM] =
+ _dbus_strdup (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS);
+ if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
+ return FALSE;
+
+ _dbus_verbose (" used default system bus \"%s\"\n",
+ bus_connection_addresses[DBUS_BUS_SYSTEM]);
}
+ else
+ _dbus_verbose (" used env var system bus \"%s\"\n",
+ bus_connection_addresses[DBUS_BUS_SYSTEM]);
if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL)
{
@@ -183,23 +187,38 @@
if (!get_from_env (&bus_connection_addresses[DBUS_BUS_ACTIVATION],
"DBUS_ACTIVATION_ADDRESS"))
return FALSE;
-
+
_dbus_verbose (" \"%s\"\n", bus_connection_addresses[DBUS_BUS_ACTIVATION] ?
bus_connection_addresses[DBUS_BUS_ACTIVATION] : "none set");
}
- s = _dbus_getenv ("DBUS_ACTIVATION_BUS_TYPE");
- if (s != NULL)
+ if (bus_connection_addresses[DBUS_BUS_ACTIVATION] != NULL)
{
- _dbus_verbose ("Bus activation type was set to \"%s\"\n", s);
-
- if (strcmp (s, "system") == 0)
- activation_bus_type = DBUS_BUS_SYSTEM;
- else if (strcmp (s, "session") == 0)
- activation_bus_type = DBUS_BUS_SESSION;
+ s = _dbus_getenv ("DBUS_ACTIVATION_BUS_TYPE");
+
+ if (s != NULL)
+ {
+ _dbus_verbose ("Bus activation type was set to \"%s\"\n", s);
+
+ if (strcmp (s, "system") == 0)
+ activation_bus_type = DBUS_BUS_SYSTEM;
+ else if (strcmp (s, "session") == 0)
+ activation_bus_type = DBUS_BUS_SESSION;
+ }
}
-
+ else
+ {
+ /* Default to the session bus instead if available */
+ if (bus_connection_addresses[DBUS_BUS_SESSION] != NULL)
+ {
+ bus_connection_addresses[DBUS_BUS_ACTIVATION] =
+ _dbus_strdup (bus_connection_addresses[DBUS_BUS_SESSION]);
+ if (bus_connection_addresses[DBUS_BUS_ACTIVATION] == NULL)
+ return FALSE;
+ }
+ }
+
/* If we return FALSE we have to be sure that restarting
* the above code will work right
*/
Index: dbus-connection.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-connection.c,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -d -r1.71 -r1.72
--- dbus-connection.c 16 Oct 2003 06:34:51 -0000 1.71
+++ dbus-connection.c 21 Oct 2003 05:46:51 -0000 1.72
@@ -1830,6 +1830,10 @@
* the whole message queue for example) and has thread issues,
* see comments in source
*
+ * Does not re-enter the main loop or run filter/path-registered
+ * callbacks. The reply to the message will not be seen by
+ * filter callbacks.
+ *
* @param connection the connection
* @param client_serial the reply serial to wait for
* @param timeout_milliseconds timeout in milliseconds or -1 for default
@@ -2430,8 +2434,15 @@
* @todo some FIXME in here about handling DBUS_HANDLER_RESULT_NEED_MEMORY
*
* @todo right now a message filter gets run on replies to a pending
- * call in here, but not in the case where we block without
- * entering the main loop.
+ * call in here, but not in the case where we block without entering
+ * the main loop. Simple solution might be to just have the pending
+ * call stuff run before the filters.
+ *
+ * @todo FIXME what if we call out to application code to handle a
+ * message, holding the dispatch lock, and the application code runs
+ * the main loop and dispatches again? Probably deadlocks at the
+ * moment. Maybe we want a dispatch status of DBUS_DISPATCH_IN_PROGRESS,
+ * and then the GSource etc. could handle the situation?
*
* @param connection the connection
* @returns dispatch status
@@ -2581,7 +2592,8 @@
dbus_message_get_type (message),
dbus_message_get_interface (message) ?
dbus_message_get_interface (message) :
- "no interface");
+ "no interface",
+ dbus_message_get_signature (message));
result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
message);
@@ -3009,7 +3021,9 @@
*
* @todo we don't run filters on messages while blocking without
* entering the main loop, since filters are run as part of
- * dbus_connection_dispatch().
+ * dbus_connection_dispatch(). This is probably a feature, as filters
+ * could create arbitrary reentrancy. But kind of sucks if you're
+ * trying to filter METHOD_RETURN for some reason.
*
* @param connection the connection
* @param function function to handle messages
Index: dbus-internals.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-internals.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- dbus-internals.c 16 Oct 2003 06:34:51 -0000 1.33
+++ dbus-internals.c 21 Oct 2003 05:46:51 -0000 1.34
@@ -380,8 +380,8 @@
return "double";
case DBUS_TYPE_STRING:
return "string";
- case DBUS_TYPE_NAMED:
- return "named";
+ case DBUS_TYPE_CUSTOM:
+ return "custom";
case DBUS_TYPE_ARRAY:
return "array";
case DBUS_TYPE_DICT:
@@ -448,7 +448,7 @@
const char *file,
int line)
{
- if (!condition)
+ if (_DBUS_UNLIKELY (!condition))
{
_dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d\n",
_dbus_getpid (), condition_text, file, line);
Index: dbus-internals.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-internals.h,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- dbus-internals.h 16 Oct 2003 06:34:51 -0000 1.38
+++ dbus-internals.h 21 Oct 2003 05:46:51 -0000 1.39
@@ -51,6 +51,33 @@
#define _DBUS_FUNCTION_NAME "unknown function"
#endif
+/*
+ * (code from GLib)
+ *
+ * The _DBUS_LIKELY and _DBUS_UNLIKELY macros let the programmer give hints to
+ * the compiler about the expected result of an expression. Some compilers
+ * can use this information for optimizations.
+ *
+ * The _DBUS_BOOLEAN_EXPR macro is intended to trigger a gcc warning when
+ * putting assignments in the macro arg
+ */
+#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
+#define _DBUS_BOOLEAN_EXPR(expr) \
+ __extension__ ({ \
+ int _dbus_boolean_var_; \
+ if (expr) \
+ _dbus_boolean_var_ = 1; \
+ else \
+ _dbus_boolean_var_ = 0; \
+ _dbus_boolean_var_; \
+})
+#define _DBUS_LIKELY(expr) (__builtin_expect (_DBUS_BOOLEAN_EXPR(expr), 1))
+#define _DBUS_UNLIKELY(expr) (__builtin_expect (_DBUS_BOOLEAN_EXPR(expr), 0))
+#else
+#define _DBUS_LIKELY(expr) (expr)
+#define _DBUS_UNLIKELY(expr) (expr)
+#endif
+
#ifdef DBUS_ENABLE_VERBOSE_MODE
# define _dbus_verbose _dbus_verbose_real
# define _dbus_verbose_reset _dbus_verbose_reset_real
Index: dbus-marshal.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-marshal.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- dbus-marshal.c 12 Oct 2003 05:59:39 -0000 1.44
+++ dbus-marshal.c 21 Oct 2003 05:46:51 -0000 1.45
@@ -1642,7 +1642,7 @@
}
break;
- case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_CUSTOM:
{
int len;
@@ -1836,7 +1836,7 @@
case DBUS_TYPE_OBJECT_PATH:
case DBUS_TYPE_STRING:
- case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_CUSTOM:
case DBUS_TYPE_ARRAY:
case DBUS_TYPE_DICT:
/* This clean recursion to validate_arg is what we
@@ -2050,7 +2050,7 @@
}
break;
- case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_CUSTOM:
{
int len;
@@ -2226,7 +2226,7 @@
case DBUS_TYPE_UINT64:
case DBUS_TYPE_DOUBLE:
case DBUS_TYPE_STRING:
- case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_CUSTOM:
case DBUS_TYPE_ARRAY:
case DBUS_TYPE_DICT:
case DBUS_TYPE_OBJECT_PATH:
Index: dbus-message-builder.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-message-builder.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- dbus-message-builder.c 30 Sep 2003 02:32:53 -0000 1.19
+++ dbus-message-builder.c 21 Oct 2003 05:46:51 -0000 1.20
@@ -735,8 +735,8 @@
code = DBUS_TYPE_STRING;
else if (_dbus_string_starts_with_c_str (&line, "OBJECT_PATH"))
code = DBUS_TYPE_OBJECT_PATH;
- else if (_dbus_string_starts_with_c_str (&line, "NAMED"))
- code = DBUS_TYPE_NAMED;
+ else if (_dbus_string_starts_with_c_str (&line, "CUSTOM"))
+ code = DBUS_TYPE_CUSTOM;
else if (_dbus_string_starts_with_c_str (&line, "ARRAY"))
code = DBUS_TYPE_ARRAY;
else if (_dbus_string_starts_with_c_str (&line, "DICT"))
Index: dbus-message.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-message.c,v
retrieving revision 1.110
retrieving revision 1.111
diff -u -d -r1.110 -r1.111
--- dbus-message.c 16 Oct 2003 06:34:51 -0000 1.110
+++ dbus-message.c 21 Oct 2003 05:46:51 -0000 1.111
@@ -488,13 +488,13 @@
case DBUS_TYPE_DOUBLE:
padding = _DBUS_ALIGN_VALUE (pos, 8) - pos;
break;
- case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_CUSTOM:
case DBUS_TYPE_ARRAY:
case DBUS_TYPE_DICT:
/* FIXME This is no good; we have to handle undefined header fields
* also. SECURITY and spec compliance issue.
*/
- _dbus_assert_not_reached ("no defined header fields may contain a named, array or dict value");
+ _dbus_assert_not_reached ("no defined header fields may contain a custom, array or dict value");
break;
case DBUS_TYPE_INVALID:
default:
@@ -1832,7 +1832,7 @@
dbus_message_append_iter_init (message, &iter);
- while (type != 0)
+ while (type != DBUS_TYPE_INVALID)
{
switch (type)
{
@@ -1873,7 +1873,7 @@
case DBUS_TYPE_OBJECT_PATH:
break;
- case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_CUSTOM:
{
const char *name;
unsigned char *data;
@@ -1883,7 +1883,7 @@
data = va_arg (var_args, unsigned char *);
len = va_arg (var_args, int);
- if (!dbus_message_iter_append_named (&iter, name, data, len))
+ if (!dbus_message_iter_append_custom (&iter, name, data, len))
goto errorout;
break;
}
@@ -1934,7 +1934,7 @@
break;
case DBUS_TYPE_NIL:
case DBUS_TYPE_ARRAY:
- case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_CUSTOM:
case DBUS_TYPE_DICT:
_dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
goto errorout;
@@ -2194,7 +2194,7 @@
break;
}
- case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_CUSTOM:
{
char **name;
unsigned char **data;
@@ -2204,7 +2204,7 @@
data = va_arg (var_args, unsigned char **);
len = va_arg (var_args, int *);
- if (!dbus_message_iter_get_named (iter, name, data, len))
+ if (!dbus_message_iter_get_custom (iter, name, data, len))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto out;
@@ -2295,7 +2295,7 @@
break;
case DBUS_TYPE_NIL:
case DBUS_TYPE_ARRAY:
- case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_CUSTOM:
case DBUS_TYPE_DICT:
_dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
@@ -2682,24 +2682,23 @@
#endif
/**
- * Returns the name and data from a named type that an
- * iterator may point to. Note that you need to check that
- * the iterator points to a named type before using this
- * function.
+ * Returns the name and data from a custom type that an iterator may
+ * point to. Note that you need to check that the iterator points to a
+ * custom type before using this function.
*
* @see dbus_message_iter_get_arg_type
* @param iter the message iter
- * @param name return location for the name
+ * @param name return location for the name of the custom type
* @param value return location for data
* @param len return location for length of data
* @returns TRUE if get succeed
*
*/
dbus_bool_t
-dbus_message_iter_get_named (DBusMessageIter *iter,
- char **name,
- unsigned char **value,
- int *len)
+dbus_message_iter_get_custom (DBusMessageIter *iter,
+ char **name,
+ unsigned char **value,
+ int *len)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
int type, pos;
@@ -2709,7 +2708,7 @@
pos = dbus_message_iter_get_data_start (real, &type);
- _dbus_assert (type == DBUS_TYPE_NAMED);
+ _dbus_assert (type == DBUS_TYPE_CUSTOM);
_name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
pos, &pos);
@@ -3773,7 +3772,7 @@
}
/**
- * Appends a named type data chunk to the message. A named
+ * Appends a custom type data chunk to the message. A custom
* type is simply an arbitrary UTF-8 string used as a type
* tag, plus an array of arbitrary bytes to be interpreted
* according to the type tag.
@@ -3785,16 +3784,16 @@
* @returns #TRUE on success
*/
dbus_bool_t
-dbus_message_iter_append_named (DBusMessageIter *iter,
- const char *name,
- const unsigned char *data,
- int len)
+dbus_message_iter_append_custom (DBusMessageIter *iter,
+ const char *name,
+ const unsigned char *data,
+ int len)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
_dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
- if (!dbus_message_iter_append_type (real, DBUS_TYPE_NAMED))
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_CUSTOM))
return FALSE;
if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
@@ -4865,6 +4864,11 @@
return TRUE;
}
+/* FIXME because the service/interface/member/error names are already
+ * validated to be in the particular ASCII subset, UTF-8 validating
+ * them could be skipped as a probably-interesting optimization.
+ * The UTF-8 validation definitely shows up in profiles.
+ */
static dbus_bool_t
decode_header_data (const DBusString *data,
int header_len,
@@ -5753,6 +5757,7 @@
#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
#include <stdio.h>
+#include <stdlib.h>
static void
message_iter_test (DBusMessage *message)
@@ -5942,13 +5947,13 @@
if (!dbus_message_iter_next (&iter))
_dbus_assert_not_reached ("Reached end of arguments");
- if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NAMED)
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_CUSTOM)
_dbus_assert_not_reached ("wrong type after dict");
- if (!dbus_message_iter_get_named (&iter, &str, &data, &len))
- _dbus_assert_not_reached ("failed to get named");
+ if (!dbus_message_iter_get_custom (&iter, &str, &data, &len))
+ _dbus_assert_not_reached ("failed to get custom type");
- _dbus_assert (strcmp (str, "named")==0);
+ _dbus_assert (strcmp (str, "MyTypeName")==0);
_dbus_assert (len == 5);
_dbus_assert (strcmp (data, "data")==0);
dbus_free (str);
@@ -6006,15 +6011,15 @@
dbus_free (str);
}
break;
- case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_CUSTOM:
{
char *name;
unsigned char *data;
int len;
- if (!dbus_message_iter_get_named (iter, &name, &data, &len))
+ if (!dbus_message_iter_get_custom (iter, &name, &data, &len))
{
- _dbus_warn ("error reading name from named type\n");
+ _dbus_warn ("error reading name from custom type\n");
return FALSE;
}
dbus_free (data);
@@ -7083,8 +7088,8 @@
dbus_message_iter_append_nil (&iter);
- dbus_message_iter_append_named (&iter, "named",
- "data", 5);
+ dbus_message_iter_append_custom (&iter, "MyTypeName",
+ "data", 5);
message_iter_test (message);
Index: dbus-message.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-message.h,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -d -r1.46 -r1.47
--- dbus-message.h 16 Oct 2003 06:34:51 -0000 1.46
+++ dbus-message.h 21 Oct 2003 05:46:51 -0000 1.47
@@ -1,7 +1,7 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-message.h DBusMessage object
*
- * Copyright (C) 2002 Red Hat Inc.
+ * Copyright (C) 2002, 2003 Red Hat Inc.
*
* Licensed under the Academic Free License version 1.2
*
@@ -164,7 +164,7 @@
char * dbus_message_iter_get_string (DBusMessageIter *iter);
char * dbus_message_iter_get_object_path (DBusMessageIter *iter);
char * dbus_message_iter_get_dict_key (DBusMessageIter *iter);
-dbus_bool_t dbus_message_iter_get_named (DBusMessageIter *iter,
+dbus_bool_t dbus_message_iter_get_custom (DBusMessageIter *iter,
char **name,
unsigned char **value,
int *len);
@@ -226,7 +226,7 @@
double value);
dbus_bool_t dbus_message_iter_append_string (DBusMessageIter *iter,
const char *value);
-dbus_bool_t dbus_message_iter_append_named (DBusMessageIter *iter,
+dbus_bool_t dbus_message_iter_append_custom (DBusMessageIter *iter,
const char *name,
const unsigned char *data,
int len);
Index: dbus-protocol.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-protocol.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- dbus-protocol.h 12 Oct 2003 00:55:11 -0000 1.23
+++ dbus-protocol.h 21 Oct 2003 05:46:51 -0000 1.24
@@ -50,9 +50,9 @@
#define DBUS_TYPE_UINT64 ((int) 't')
#define DBUS_TYPE_DOUBLE ((int) 'd')
#define DBUS_TYPE_STRING ((int) 's')
-#define DBUS_TYPE_NAMED ((int) 'n')
+#define DBUS_TYPE_CUSTOM ((int) 'c')
#define DBUS_TYPE_ARRAY ((int) 'a')
-#define DBUS_TYPE_DICT ((int) 'c')
+#define DBUS_TYPE_DICT ((int) 'm')
#define DBUS_TYPE_OBJECT_PATH ((int) 'o')
#define DBUS_NUMBER_OF_TYPES (13)
Index: dbus-string.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-string.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -d -r1.42 -r1.43
--- dbus-string.c 30 Sep 2003 02:32:53 -0000 1.42
+++ dbus-string.c 21 Oct 2003 05:46:51 -0000 1.43
@@ -544,7 +544,9 @@
}
/**
- * Gets the byte at the given position.
+ * Gets the byte at the given position. It is
+ * allowed to ask for the nul byte at the end of
+ * the string.
*
* @param str the string
* @param start the position
@@ -555,7 +557,7 @@
int start)
{
DBUS_CONST_STRING_PREAMBLE (str);
- _dbus_assert (start < real->len);
+ _dbus_assert (start <= real->len);
_dbus_assert (start >= 0);
return real->str[start];
@@ -2728,8 +2730,8 @@
end = s + len;
while (s != end)
{
- if (*s == '\0' ||
- ((*s & ~0x7f) != 0))
+ if (_DBUS_UNLIKELY (*s == '\0' ||
+ ((*s & ~0x7f) != 0)))
return FALSE;
++s;
@@ -2765,7 +2767,15 @@
_dbus_assert (start <= real->len);
_dbus_assert (len >= 0);
- if (len > real->len - start)
+ /* we are doing _DBUS_UNLIKELY() here which might be
+ * dubious in a generic library like GLib, but in D-BUS
+ * we know we're validating messages and that it would
+ * only be evil/broken apps that would have invalid
+ * UTF-8. Also, this function seems to be a performance
+ * bottleneck in profiles.
+ */
+
+ if (_DBUS_UNLIKELY (len > real->len - start))
return FALSE;
p = real->str + start;
@@ -2779,22 +2789,22 @@
UTF8_COMPUTE (c, mask, char_len);
- if (char_len == -1)
+ if (_DBUS_UNLIKELY (char_len == -1))
break;
/* check that the expected number of bytes exists in the remaining length */
- if ((end - p) < char_len)
+ if (_DBUS_UNLIKELY ((end - p) < char_len))
break;
UTF8_GET (result, p, i, mask, char_len);
- if (UTF8_LENGTH (result) != char_len) /* Check for overlong UTF-8 */
+ if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* Check for overlong UTF-8 */
break;
- if (result == (dbus_unichar_t)-1)
+ if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1))
break;
- if (!UNICODE_VALID (result))
+ if (_DBUS_UNLIKELY (!UNICODE_VALID (result)))
break;
p += char_len;
@@ -2803,7 +2813,7 @@
/* See that we covered the entire length if a length was
* passed in
*/
- if (p != end)
+ if (_DBUS_UNLIKELY (p != end))
return FALSE;
else
return TRUE;
@@ -2841,7 +2851,7 @@
end = s + len;
while (s != end)
{
- if (*s != '\0')
+ if (_DBUS_UNLIKELY (*s != '\0'))
return FALSE;
++s;
}
@@ -2917,17 +2927,24 @@
return TRUE;
}
+#define VALID_INITIAL_NAME_CHARACTER(c) \
+ ( ((c) >= 'A' && (c) <= 'Z') || \
+ ((c) >= 'a' && (c) <= 'z') || \
+ ((c) == '_') )
+
+#define VALID_NAME_CHARACTER(c) \
+ ( ((c) >= '0' && (c) <= '9') || \
+ ((c) >= 'A' && (c) <= 'Z') || \
+ ((c) >= 'a' && (c) <= 'z') || \
+ ((c) == '_') )
+
/**
* Checks that the given range of the string is a valid interface name
- * in the D-BUS protocol. This includes a length restriction, etc.,
- * see the specification. It does not validate UTF-8, that has to be
- * done separately for now.
+ * in the D-BUS protocol. This includes a length restriction and an
+ * ASCII subset, see the specification.
*
* @todo this is inconsistent with most of DBusString in that
* it allows a start,len range that isn't in the string.
- *
- * @todo change spec to disallow more things, such as spaces in the
- * interface name
*
* @param str the string
* @param start first byte index to check
@@ -2938,10 +2955,11 @@
_dbus_string_validate_interface (const DBusString *str,
int start,
int len)
-{
+{
const unsigned char *s;
const unsigned char *end;
- dbus_bool_t saw_dot;
+ const unsigned char *iface;
+ const unsigned char *last_dot;
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (start >= 0);
@@ -2957,21 +2975,41 @@
if (len == 0)
return FALSE;
- saw_dot = FALSE;
- s = real->str + start;
- end = s + len;
+ last_dot = NULL;
+ iface = real->str + start;
+ end = iface + len;
+ s = iface;
+
+ /* check special cases of first char so it doesn't have to be done
+ * in the loop. Note we know len > 0
+ */
+ if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
+ return FALSE;
+ else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
+ return FALSE;
+ else
+ ++s;
+
while (s != end)
{
if (*s == '.')
{
- saw_dot = TRUE;
- break;
+ if (_DBUS_UNLIKELY ((s + 1) == end))
+ return FALSE;
+ else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1))))
+ return FALSE;
+ last_dot = s;
+ ++s; /* we just validated the next char, so skip two */
+ }
+ else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
+ {
+ return FALSE;
}
++s;
}
- if (!saw_dot)
+ if (_DBUS_UNLIKELY (last_dot == NULL))
return FALSE;
return TRUE;
@@ -2980,15 +3018,11 @@
/**
* Checks that the given range of the string is a valid member name
* in the D-BUS protocol. This includes a length restriction, etc.,
- * see the specification. It does not validate UTF-8, that has to be
- * done separately for now.
+ * see the specification.
*
* @todo this is inconsistent with most of DBusString in that
* it allows a start,len range that isn't in the string.
*
- * @todo change spec to disallow more things, such as spaces in the
- * member name
- *
* @param str the string
* @param start first byte index to check
* @param len number of bytes to check
@@ -3001,7 +3035,7 @@
{
const unsigned char *s;
const unsigned char *end;
- dbus_bool_t saw_dot;
+ const unsigned char *member;
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (start >= 0);
@@ -3017,23 +3051,28 @@
if (len == 0)
return FALSE;
- saw_dot = FALSE;
- s = real->str + start;
- end = s + len;
+ member = real->str + start;
+ end = member + len;
+ s = member;
+
+ /* check special cases of first char so it doesn't have to be done
+ * in the loop. Note we know len > 0
+ */
+
+ if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
+ return FALSE;
+ else
+ ++s;
+
while (s != end)
{
- if (*s == '.')
+ if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
{
- saw_dot = TRUE;
- break;
+ return FALSE;
}
++s;
}
-
- /* No dot allowed in member names */
- if (saw_dot)
- return FALSE;
return TRUE;
}
@@ -3041,8 +3080,7 @@
/**
* Checks that the given range of the string is a valid error name
* in the D-BUS protocol. This includes a length restriction, etc.,
- * see the specification. It does not validate UTF-8, that has to be
- * done separately for now.
+ * see the specification.
*
* @todo this is inconsistent with most of DBusString in that
* it allows a start,len range that isn't in the string.
@@ -3061,32 +3099,15 @@
return _dbus_string_validate_interface (str, start, len);
}
-/**
- * Checks that the given range of the string is a valid service name
- * in the D-BUS protocol. This includes a length restriction, etc.,
- * see the specification. It does not validate UTF-8, that has to be
- * done separately for now.
- *
- * @todo this is inconsistent with most of DBusString in that
- * it allows a start,len range that isn't in the string.
- *
- * @todo change spec to disallow more things, such as spaces in the
- * service name
- *
- * @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_string_validate_service (const DBusString *str,
- int start,
- int len)
+/* This assumes the first char exists and is ':' */
+static dbus_bool_t
+_dbus_string_validate_base_service (const DBusString *str,
+ int start,
+ int len)
{
const unsigned char *s;
const unsigned char *end;
- dbus_bool_t saw_dot;
- dbus_bool_t is_base_service;
+ const unsigned char *service;
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (start >= 0);
@@ -3099,30 +3120,58 @@
if (len > DBUS_MAXIMUM_NAME_LENGTH)
return FALSE;
- if (len == 0)
- return FALSE;
-
- is_base_service = _dbus_string_get_byte (str, start) == ':';
- if (is_base_service)
- return TRUE; /* can have any content */
+ _dbus_assert (len > 0);
- /* non-base-service must have the '.' indicating a namespace */
+ service = real->str + start;
+ end = service + len;
+ _dbus_assert (*service == ':');
+ s = service + 1;
- saw_dot = FALSE;
- s = real->str + start;
- end = s + len;
while (s != end)
{
if (*s == '.')
{
- saw_dot = TRUE;
- break;
+ if (_DBUS_UNLIKELY ((s + 1) == end))
+ return FALSE;
+ if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*(s + 1))))
+ return FALSE;
+ ++s; /* we just validated the next char, so skip two */
+ }
+ else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
+ {
+ return FALSE;
}
++s;
}
- return saw_dot;
+ return TRUE;
+}
+
+/**
+ * Checks that the given range of the string is a valid service 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 isn't in the string.
+ *
+ * @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_string_validate_service (const DBusString *str,
+ int start,
+ int len)
+{
+ if (_DBUS_UNLIKELY (len == 0))
+ return FALSE;
+ if (_dbus_string_get_byte (str, start) == ':')
+ return _dbus_string_validate_base_service (str, start, len);
+ else
+ return _dbus_string_validate_interface (str, start, len);
}
/**
@@ -3339,7 +3388,95 @@
"//",
"///",
"foo///blah/",
- "Hello World"
+ "Hello World",
+ "",
+ " ",
+ "foo bar"
+ };
+
+ const char *valid_interfaces[] = {
+ "org.freedesktop.Foo",
+ "Bar.Baz",
+ "Blah.Blah.Blah.Blah.Blah",
+ "a.b",
+ "a.b.c.d.e.f.g",
+ "a0.b1.c2.d3.e4.f5.g6",
+ "abc123.foo27"
+ };
+ const char *invalid_interfaces[] = {
+ ".",
+ "",
+ "..",
+ ".Foo.Bar",
+ "..Foo.Bar",
+ "Foo.Bar.",
+ "Foo.Bar..",
+ "Foo",
+ "9foo.bar.baz",
+ "foo.bar..baz",
+ "foo.bar...baz",
+ "foo.bar.b..blah",
+ ":",
+ ":0-1",
+ "10",
+ ":11.34324",
+ "0.0.0",
+ "0..0",
+ "foo.Bar.%",
+ "foo.Bar!!",
+ "!Foo.bar.bz",
+ "foo.$.blah",
+ "",
+ " ",
+ "foo bar"
+ };
+
+ const char *valid_base_services[] = {
+ ":0",
+ ":a",
+ ":",
+ ":.a",
+ ":.1",
+ ":0.1",
+ ":000.2222",
+ ":.blah",
+ ":abce.freedesktop.blah"
+ };
+ const char *invalid_base_services[] = {
+ ":-",
+ ":!",
+ ":0-10",
+ ":blah.",
+ ":blah.",
+ ":blah..org",
+ ":blah.org..",
+ ":..blah.org",
+ "",
+ " ",
+ "foo bar"
+ };
+
+ const char *valid_members[] = {
+ "Hello",
+ "Bar",
+ "foobar",
+ "_foobar",
+ "foo89"
+ };
+
+ const char *invalid_members[] = {
+ "9Hello",
+ "10",
+ "1",
+ "foo-bar",
+ "blah.org",
+ ".blah",
+ "blah.",
+ "Hello.",
+ "!foo",
+ "",
+ " ",
+ "foo bar"
};
i = 0;
@@ -3749,7 +3886,221 @@
++i;
}
-
+
+ /* Interface validation */
+ i = 0;
+ while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
+ {
+ _dbus_string_init_const (&str, valid_interfaces[i]);
+
+ if (!_dbus_string_validate_interface (&str, 0,
+ _dbus_string_get_length (&str)))
+ {
+ _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]);
+ _dbus_assert_not_reached ("invalid interface");
+ }
+
+ ++i;
+ }
+
+ i = 0;
+ while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
+ {
+ _dbus_string_init_const (&str, invalid_interfaces[i]);
+
+ if (_dbus_string_validate_interface (&str, 0,
+ _dbus_string_get_length (&str)))
+ {
+ _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]);
+ _dbus_assert_not_reached ("valid interface");
+ }
+
+ ++i;
+ }
+
+ /* Service validation (check that valid interfaces are valid services,
+ * and invalid interfaces are invalid services except if they start with ':')
+ */
+ i = 0;
+ while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
+ {
+ _dbus_string_init_const (&str, valid_interfaces[i]);
+
+ if (!_dbus_string_validate_service (&str, 0,
+ _dbus_string_get_length (&str)))
+ {
+ _dbus_warn ("Service \"%s\" should have been valid\n", valid_interfaces[i]);
+ _dbus_assert_not_reached ("invalid service");
+ }
+
+ ++i;
+ }
+
+ i = 0;
+ while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
+ {
+ if (invalid_interfaces[i][0] != ':')
+ {
+ _dbus_string_init_const (&str, invalid_interfaces[i]);
+
+ if (_dbus_string_validate_service (&str, 0,
+ _dbus_string_get_length (&str)))
+ {
+ _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_interfaces[i]);
+ _dbus_assert_not_reached ("valid service");
+ }
+ }
+
+ ++i;
+ }
+
+ /* Base service validation */
+ i = 0;
+ while (i < (int) _DBUS_N_ELEMENTS (valid_base_services))
+ {
+ _dbus_string_init_const (&str, valid_base_services[i]);
+
+ if (!_dbus_string_validate_service (&str, 0,
+ _dbus_string_get_length (&str)))
+ {
+ _dbus_warn ("Service \"%s\" should have been valid\n", valid_base_services[i]);
+ _dbus_assert_not_reached ("invalid base service");
+ }
+
+ ++i;
+ }
+
+ i = 0;
+ while (i < (int) _DBUS_N_ELEMENTS (invalid_base_services))
+ {
+ _dbus_string_init_const (&str, invalid_base_services[i]);
+
+ if (_dbus_string_validate_service (&str, 0,
+ _dbus_string_get_length (&str)))
+ {
+ _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_base_services[i]);
+ _dbus_assert_not_reached ("valid base service");
+ }
+
+ ++i;
+ }
+
+
+ /* Error name validation (currently identical to interfaces)
+ */
+ i = 0;
+ while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
+ {
+ _dbus_string_init_const (&str, valid_interfaces[i]);
+
+ if (!_dbus_string_validate_error_name (&str, 0,
+ _dbus_string_get_length (&str)))
+ {
+ _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]);
+ _dbus_assert_not_reached ("invalid error name");
+ }
+
+ ++i;
+ }
+
+ i = 0;
+ while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
+ {
+ if (invalid_interfaces[i][0] != ':')
+ {
+ _dbus_string_init_const (&str, invalid_interfaces[i]);
+
+ if (_dbus_string_validate_error_name (&str, 0,
+ _dbus_string_get_length (&str)))
+ {
+ _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]);
+ _dbus_assert_not_reached ("valid error name");
+ }
+ }
+
+ ++i;
+ }
+
+ /* Member validation */
+ i = 0;
+ while (i < (int) _DBUS_N_ELEMENTS (valid_members))
+ {
+ _dbus_string_init_const (&str, valid_members[i]);
+
+ if (!_dbus_string_validate_member (&str, 0,
+ _dbus_string_get_length (&str)))
+ {
+ _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]);
+ _dbus_assert_not_reached ("invalid member");
+ }
+
+ ++i;
+ }
+
+ i = 0;
+ while (i < (int) _DBUS_N_ELEMENTS (invalid_members))
+ {
+ _dbus_string_init_const (&str, invalid_members[i]);
+
+ if (_dbus_string_validate_member (&str, 0,
+ _dbus_string_get_length (&str)))
+ {
+ _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]);
+ _dbus_assert_not_reached ("valid member");
+ }
+
+ ++i;
+ }
+
+ /* Validate claimed length longer than real length */
+ _dbus_string_init_const (&str, "abc.efg");
+ if (_dbus_string_validate_service (&str, 0, 8))
+ _dbus_assert_not_reached ("validated too-long string");
+ if (_dbus_string_validate_interface (&str, 0, 8))
+ _dbus_assert_not_reached ("validated too-long string");
+ if (_dbus_string_validate_error_name (&str, 0, 8))
+ _dbus_assert_not_reached ("validated too-long string");
+
+ _dbus_string_init_const (&str, "abc");
+ if (_dbus_string_validate_member (&str, 0, 4))
+ _dbus_assert_not_reached ("validated too-long string");
+
+ /* Validate string exceeding max name length */
+ if (!_dbus_string_init (&str))
+ _dbus_assert_not_reached ("no memory");
+
+ while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
+ if (!_dbus_string_append (&str, "abc.def"))
+ _dbus_assert_not_reached ("no memory");
+
+ if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str)))
+ _dbus_assert_not_reached ("validated overmax string");
+ if (_dbus_string_validate_interface (&str, 0, _dbus_string_get_length (&str)))
+ _dbus_assert_not_reached ("validated overmax string");
+ if (_dbus_string_validate_error_name (&str, 0, _dbus_string_get_length (&str)))
+ _dbus_assert_not_reached ("validated overmax string");
+
+ /* overlong member */
+ _dbus_string_set_length (&str, 0);
+ while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
+ if (!_dbus_string_append (&str, "abc"))
+ _dbus_assert_not_reached ("no memory");
+
+ if (_dbus_string_validate_member (&str, 0, _dbus_string_get_length (&str)))
+ _dbus_assert_not_reached ("validated overmax string");
+
+ /* overlong base service */
+ _dbus_string_set_length (&str, 0);
+ _dbus_string_append (&str, ":");
+ while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
+ if (!_dbus_string_append (&str, "abc"))
+ _dbus_assert_not_reached ("no memory");
+
+ if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str)))
+ _dbus_assert_not_reached ("validated overmax string");
+
+ _dbus_string_free (&str);
+
return TRUE;
}
Index: dbus-string.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-string.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- dbus-string.h 30 Sep 2003 02:32:53 -0000 1.21
+++ dbus-string.h 21 Oct 2003 05:46:52 -0000 1.22
@@ -1,7 +1,7 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-string.h String utility class (internal to D-BUS implementation)
*
- * Copyright (C) 2002 Red Hat, Inc.
+ * Copyright (C) 2002, 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*