diff options
| -rw-r--r-- | ChangeLog | 25 | ||||
| -rw-r--r-- | bus/activation.c | 71 | ||||
| -rw-r--r-- | bus/config-loader-libxml.c | 265 | ||||
| -rw-r--r-- | configure.in | 5 | ||||
| -rw-r--r-- | dbus/dbus-message.c | 18 | ||||
| -rw-r--r-- | dbus/dbus-transport-unix.c | 24 | ||||
| -rw-r--r-- | glib/Makefile.am | 2 | ||||
| -rw-r--r-- | test/data/invalid-config-files/not-well-formed.conf | 5 | ||||
| -rw-r--r-- | test/data/invalid-config-files/truncated-file.conf | 9 | 
9 files changed, 310 insertions, 114 deletions
| @@ -1,3 +1,28 @@ +2004-07-29  Olivier Andrieu  <oliv__a@users.sourceforge.net> + +	* bus/config-loader-libxml.c: complete the implementation of +	libxml backend for config file loader. Doesn't work with full OOM +	test yet.  +	 +	* configure.in: change error when selecting libxml into a warning. +	 +	* test/data/invalid-config-files: add two non-well-formed XML +	files.  +	 +	* glib/Makefile.am: libdbus_gtool always uses expat, not libxml. +	 +	* dbus/dbus-transport-unix.c (unix_handle_watch): do not +	disconnect in case of DBUS_WATCH_HANGUP, several do_reading() may +	be necessary to read all the buffer. (bug #894) + +	* bus/activation.c (bus_activation_activate_service): fix a +	potential assertion failure (bug #896). Small optimization in the +	case of auto-activation messages. + +	* dbus/dbus-message.c (verify_test_message, _dbus_message_test): +	add test case for byte-through-vararg bug (#901). patch by Kimmo +	Hämäläinen.  +  2004-07-28  Anders Carlsson  <andersca@gnome.org>  	* python/dbus.py: diff --git a/bus/activation.c b/bus/activation.c index e286ba9d..b799948f 100644 --- a/bus/activation.c +++ b/bus/activation.c @@ -44,7 +44,7 @@ struct BusActivation    int refcount;    DBusHashTable *entries;    DBusHashTable *pending_activations; - char *server_address; +  char *server_address;    BusContext *context;    int n_pending_activations; /**< This is in fact the number of BusPendingActivationEntry,                                * i.e. number of pending activation requests, not pending @@ -1319,40 +1319,46 @@ bus_activation_activate_service (BusActivation  *activation,    if (!entry)       return FALSE; -  /* Check if the service is active */ -  _dbus_string_init_const (&service_str, service_name); -  if (bus_registry_lookup (bus_context_get_registry (activation->context), &service_str) != NULL) +  /* Bypass the registry lookup if we're auto-activating, bus_dispatch would not +   * call us if the service is already active. +   */ +  if (!auto_activation)      { -      _dbus_verbose ("Service \"%s\" is already active\n", service_name); +      /* Check if the service is active */ +      _dbus_string_init_const (&service_str, service_name); +      if (bus_registry_lookup (bus_context_get_registry (activation->context), &service_str) != NULL) +        { +          _dbus_verbose ("Service \"%s\" is already active\n", service_name); -      message = dbus_message_new_method_return (activation_message); +          message = dbus_message_new_method_return (activation_message); -      if (!message) -	{ -          _dbus_verbose ("No memory to create reply to activate message\n"); -	  BUS_SET_OOM (error); -	  return FALSE; -	} +          if (!message) +            { +              _dbus_verbose ("No memory to create reply to activate message\n"); +              BUS_SET_OOM (error); +              return FALSE; +            } -      if (!dbus_message_append_args (message, -				     DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE,  -				     DBUS_TYPE_INVALID)) -	{ -          _dbus_verbose ("No memory to set args of reply to activate message\n"); -	  BUS_SET_OOM (error); -	  dbus_message_unref (message); -	  return FALSE; -	} +          if (!dbus_message_append_args (message, +                                         DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE,  +                                         DBUS_TYPE_INVALID)) +            { +              _dbus_verbose ("No memory to set args of reply to activate message\n"); +              BUS_SET_OOM (error); +              dbus_message_unref (message); +              return FALSE; +            } -      retval = bus_transaction_send_from_driver (transaction, connection, message); -      dbus_message_unref (message); -      if (!retval) -        { -          _dbus_verbose ("Failed to send reply\n"); -          BUS_SET_OOM (error); -        } +          retval = bus_transaction_send_from_driver (transaction, connection, message); +          dbus_message_unref (message); +          if (!retval) +            { +              _dbus_verbose ("Failed to send reply\n"); +              BUS_SET_OOM (error); +            } -      return retval; +          return retval; +        }      }    pending_activation_entry = dbus_new0 (BusPendingActivationEntry, 1); @@ -1504,11 +1510,8 @@ bus_activation_activate_service (BusActivation  *activation,     * argv[0]     */ -  if (activated == TRUE)  -    { -      pending_activation->babysitter = NULL; -      return TRUE; -    } +  if (activated) +    return TRUE;    /* Now try to spawn the process */    argv[0] = entry->exec; diff --git a/bus/config-loader-libxml.c b/bus/config-loader-libxml.c index 054acc6e..a1b8f838 100644 --- a/bus/config-loader-libxml.c +++ b/bus/config-loader-libxml.c @@ -30,46 +30,112 @@  #include <errno.h>  #include <string.h> -static void* -libxml_malloc (size_t size) -{ -  return dbus_malloc (size); -} +/* About the error handling:  + *  - setup a "structured" error handler that catches structural + *    errors and some oom errors  + *  - assume that a libxml function returning an error code means + *    out-of-memory + */ +#define _DBUS_MAYBE_SET_OOM(e) (dbus_error_is_set(e) ? (void)0 : _DBUS_SET_OOM(e)) -static void* -libxml_realloc (void *ptr, size_t size) -{ -  return dbus_realloc (ptr, size); -} -static void -libxml_free (void *ptr) +static dbus_bool_t +xml_text_start_element (BusConfigParser   *parser, +			xmlTextReader     *reader, +			DBusError         *error)  { -  dbus_free (ptr); +  const char *name; +  int n_attributes; +  const char **attribute_names, **attribute_values; +  dbus_bool_t ret; +  int i, status, is_empty; + +  _DBUS_ASSERT_ERROR_IS_CLEAR (error); + +  ret = FALSE; +  attribute_names = NULL; +  attribute_values = NULL; + +  name = xmlTextReaderConstName (reader); +  n_attributes = xmlTextReaderAttributeCount (reader); +  is_empty = xmlTextReaderIsEmptyElement (reader); + +  if (name == NULL || n_attributes < 0 || is_empty == -1) +    { +      _DBUS_MAYBE_SET_OOM (error); +      goto out; +    } + +  attribute_names = dbus_new0 (const char *, n_attributes + 1); +  attribute_values = dbus_new0 (const char *, n_attributes + 1); +  if (attribute_names == NULL || attribute_values == NULL) +    { +      _DBUS_SET_OOM (error); +      goto out; +    } +  i = 0; +  while ((status = xmlTextReaderMoveToNextAttribute (reader)) == 1) +    { +      _dbus_assert (i < n_attributes); +      attribute_names[i] = xmlTextReaderConstName (reader); +      attribute_values[i] = xmlTextReaderConstValue (reader); +      if (attribute_names[i] == NULL || attribute_values[i] == NULL) +	{  +          _DBUS_MAYBE_SET_OOM (error); +	  goto out; +	} +      i++; +    } +  if (status == -1) +    { +      _DBUS_MAYBE_SET_OOM (error); +      goto out; +    } +  _dbus_assert (i == n_attributes); + +  ret = bus_config_parser_start_element (parser, name, +					 attribute_names, attribute_values, +					 error); +  if (ret && is_empty == 1) +    ret = bus_config_parser_end_element (parser, name, error); + + out: +  dbus_free (attribute_names); +  dbus_free (attribute_values); + +  return ret;  } -static char* -libxml_strdup (const char *str) +static void xml_shut_up (void *ctx, const char *msg, ...)  { -  return _dbus_strdup (str); +    return;  }  static void -xml_text_reader_error (void                   *arg, -                       const char             *msg, -                       xmlParserSeverities     severity, -                       xmlTextReaderLocatorPtr locator) +xml_text_reader_error (void *arg, xmlErrorPtr xml_error)  {    DBusError *error = arg; -   -  if (!dbus_error_is_set (error)) + +#if 0 +  _dbus_verbose ("XML_ERROR level=%d, domain=%d, code=%d, msg=%s\n", +                 xml_error->level, xml_error->domain, +                 xml_error->code, xml_error->message); +#endif + +  if (!dbus_error_is_set (error) &&  +      (xml_error->level == XML_ERR_ERROR || +       xml_error->level == XML_ERR_FATAL))      { -      dbus_set_error (error, DBUS_ERROR_FAILED, -                      "Error loading config file: %s", -                      msg); +      if (xml_error->code != XML_ERR_NO_MEMORY) +        _DBUS_SET_OOM (error); +      else +        dbus_set_error (error, DBUS_ERROR_FAILED, +                        "Error loading config file: '%s'", +                        xml_error->message);      }  } +  BusConfigParser*  bus_config_load (const DBusString      *file,                   dbus_bool_t            is_toplevel, @@ -78,66 +144,71 @@ bus_config_load (const DBusString      *file,  {    xmlTextReader *reader; -  const char *filename;    BusConfigParser *parser; -  DBusString dirname; +  DBusString dirname, data; +  const char *data_str;    DBusError tmp_error;    int ret;    _DBUS_ASSERT_ERROR_IS_CLEAR (error); -  filename = _dbus_string_get_const_data (file);    parser = NULL;    reader = NULL; -  dbus_error_init (&tmp_error); -  if (xmlMemSetup (libxml_free, -                   libxml_malloc, -                   libxml_realloc, -                   libxml_strdup) != 0) +  if (is_toplevel)      { -      /* Current libxml can't possibly fail here, but just being -       * paranoid; don't really know why xmlMemSetup() returns an -       * error code, assuming some version of libxml had a reason. -       */ -      dbus_set_error (error, DBUS_ERROR_FAILED, -                      "xmlMemSetup() didn't work for some reason\n"); -      return NULL; +      /* xmlMemSetup only fails if one of the functions is NULL */ +      xmlMemSetup (dbus_free, +                   dbus_malloc, +                   dbus_realloc, +                   _dbus_strdup); +      xmlInitParser (); +      xmlSetGenericErrorFunc (NULL, xml_shut_up);      }    if (!_dbus_string_init (&dirname))      { -      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); +      _DBUS_SET_OOM (error); +      return NULL; +    } + +  if (!_dbus_string_init (&data)) +    { +      _DBUS_SET_OOM (error); +      _dbus_string_free (&dirname);        return NULL;      }    if (!_dbus_string_get_dirname (file, &dirname))      { -      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); +      _DBUS_SET_OOM (error);        goto failed;      }    parser = bus_config_parser_new (&dirname, is_toplevel, parent);    if (parser == NULL)      { -      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); +      _DBUS_SET_OOM (error);        goto failed;      } -  errno = 0; -  reader = xmlNewTextReaderFilename (filename); +  if (!_dbus_file_get_contents (&data, file, error)) +    goto failed; + +  data_str = _dbus_string_get_const_data (&data); +  reader = xmlReaderForMemory (data_str, _dbus_string_get_length (&data), +			       NULL, NULL, 0);    if (reader == NULL)      { -      dbus_set_error (error, DBUS_ERROR_FAILED, -                      "Failed to load configuration file %s: %s\n", -                      filename, -                      errno != 0 ? strerror (errno) : "Unknown error"); -         +      _DBUS_SET_OOM (error);        goto failed;      } -  xmlTextReaderSetErrorHandler (reader, xml_text_reader_error, &tmp_error); +  xmlTextReaderSetParserProp (reader, XML_PARSER_SUBST_ENTITIES, 1); + +  dbus_error_init (&tmp_error); +  xmlTextReaderSetStructuredErrorHandler (reader, xml_text_reader_error, &tmp_error);    while ((ret = xmlTextReaderRead (reader)) == 1)      { @@ -145,31 +216,87 @@ bus_config_load (const DBusString      *file,        if (dbus_error_is_set (&tmp_error))          goto reader_out; -       -      /* "enum" anyone? http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html for -       * the magic numbers -       */ +        type = xmlTextReaderNodeType (reader); +      if (type == -1) +        { +          _DBUS_MAYBE_SET_OOM (&tmp_error); +          goto reader_out; +        } + +      switch ((xmlReaderTypes) type) { +      case XML_READER_TYPE_ELEMENT: +	xml_text_start_element (parser, reader, &tmp_error); +	break; + +      case XML_READER_TYPE_TEXT: +      case XML_READER_TYPE_CDATA: +	{ +	  DBusString content; +	  const char *value; +	  value = xmlTextReaderConstValue (reader); +	  if (value != NULL) +	    { +	      _dbus_string_init_const (&content, value); +	      bus_config_parser_content (parser, &content, &tmp_error); +	    } +          else +            _DBUS_MAYBE_SET_OOM (&tmp_error); +	  break; +	} + +      case XML_READER_TYPE_DOCUMENT_TYPE: +	{ +	  const char *name; +	  name = xmlTextReaderConstName (reader); +	  if (name != NULL) +	    bus_config_parser_check_doctype (parser, name, &tmp_error); +          else +            _DBUS_MAYBE_SET_OOM (&tmp_error); +	  break; +	} + +      case XML_READER_TYPE_END_ELEMENT: +	{ +	  const char *name; +	  name = xmlTextReaderConstName (reader); +	  if (name != NULL) +	    bus_config_parser_end_element (parser, name, &tmp_error); +          else +            _DBUS_MAYBE_SET_OOM (&tmp_error); +	  break; +	} + +      case XML_READER_TYPE_DOCUMENT: +      case XML_READER_TYPE_DOCUMENT_FRAGMENT: +      case XML_READER_TYPE_PROCESSING_INSTRUCTION: +      case XML_READER_TYPE_COMMENT: +      case XML_READER_TYPE_ENTITY: +      case XML_READER_TYPE_NOTATION: +      case XML_READER_TYPE_WHITESPACE: +      case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: +      case XML_READER_TYPE_END_ENTITY: +      case XML_READER_TYPE_XML_DECLARATION: +	/* nothing to do, just read on */ +	break; + +      case XML_READER_TYPE_NONE: +      case XML_READER_TYPE_ATTRIBUTE: +      case XML_READER_TYPE_ENTITY_REFERENCE: +	_dbus_assert_not_reached ("unexpected nodes in XML"); +      } +        if (dbus_error_is_set (&tmp_error))          goto reader_out; - -      /* FIXME I don't really know exactly what I need to do to -       * resolve all entities and so on to get the full content of a -       * node or attribute value. I'm worried about whether I need to -       * manually handle stuff like < -       */      }    if (ret == -1) -    { -      if (!dbus_error_is_set (&tmp_error)) -        dbus_set_error (&tmp_error, -                        DBUS_ERROR_FAILED, -                        "Unknown failure loading configuration file"); -    } -   +    _DBUS_MAYBE_SET_OOM (&tmp_error); +   reader_out:    xmlFreeTextReader (reader); +  if (is_toplevel) +    xmlCleanupParser();     reader = NULL;    if (dbus_error_is_set (&tmp_error))      { @@ -180,12 +307,14 @@ bus_config_load (const DBusString      *file,    if (!bus_config_parser_finished (parser, error))      goto failed;    _dbus_string_free (&dirname); +  _dbus_string_free (&data);    _DBUS_ASSERT_ERROR_IS_CLEAR (error);    return parser;   failed:    _DBUS_ASSERT_ERROR_IS_SET (error);    _dbus_string_free (&dirname); +  _dbus_string_free (&data);    if (parser)      bus_config_parser_unref (parser);    _dbus_assert (reader == NULL); /* must go to reader_out first */ diff --git a/configure.in b/configure.in index 17b34018..2c18dd45 100644 --- a/configure.in +++ b/configure.in @@ -673,10 +673,11 @@ else  fi  if $dbus_use_libxml ; then -	dnl libxml loader is broken -	AC_MSG_ERROR([libxml loader is broken ATM, use the expat loader]) +	dnl libxml OOM handling is a bit broken +	AC_MSG_WARN([libxml loader is not as robust as the expat one wrt. OOM handling])  fi +  AM_CONDITIONAL(DBUS_USE_EXPAT, $dbus_use_expat)  AM_CONDITIONAL(DBUS_USE_LIBXML, $dbus_use_libxml) diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 8887720a..1db8bd9c 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -2622,7 +2622,7 @@ dbus_message_iter_get_args_valist (DBusMessageIter *iter,  #endif /* DBUS_HAVE_INT64 */  	case DBUS_TYPE_DOUBLE:  	  { -	    void *ptr = va_arg (var_args, void *); +	    void *ptr = va_arg (var_args, double *);  	    _dbus_message_iter_get_basic_type (iter, spec_type, ptr);  	    break;  	  } @@ -6696,6 +6696,7 @@ verify_test_message (DBusMessage *message)    char *our_str;    double our_double;    dbus_bool_t our_bool; +  unsigned char our_byte_1, our_byte_2;    dbus_uint32_t our_uint32;    dbus_int32_t *our_uint32_array;    int our_uint32_array_len; @@ -6730,6 +6731,9 @@ verify_test_message (DBusMessage *message)  				   DBUS_TYPE_STRING, &our_str,  				   DBUS_TYPE_DOUBLE, &our_double,  				   DBUS_TYPE_BOOLEAN, &our_bool, +				   DBUS_TYPE_BYTE, &our_byte_1, +				   DBUS_TYPE_BYTE, &our_byte_2, +				   DBUS_TYPE_NIL,  				   DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,                                     &our_uint32_array, &our_uint32_array_len,                                     DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, @@ -6775,6 +6779,12 @@ verify_test_message (DBusMessage *message)    if (!our_bool)      _dbus_assert_not_reached ("booleans differ"); +  if (our_byte_1 != 42) +    _dbus_assert_not_reached ("bytes differ!"); + +  if (our_byte_2 != 24) +    _dbus_assert_not_reached ("bytes differ!"); +    if (our_uint32_array_len != 4 ||        our_uint32_array[0] != 0x12345678 ||        our_uint32_array[1] != 0x23456781 || @@ -7027,6 +7037,9 @@ _dbus_message_test (const char *test_data_dir)  			    DBUS_TYPE_STRING, "Test string",  			    DBUS_TYPE_DOUBLE, 3.14159,  			    DBUS_TYPE_BOOLEAN, TRUE, +			    DBUS_TYPE_BYTE, (unsigned char) 42, +			    DBUS_TYPE_BYTE, 24, +			    DBUS_TYPE_NIL,  			    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_uint32_array,                              _DBUS_N_ELEMENTS (our_uint32_array),                              DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, our_int32_array, @@ -7062,6 +7075,9 @@ _dbus_message_test (const char *test_data_dir)    sig[i++] = DBUS_TYPE_STRING;    sig[i++] = DBUS_TYPE_DOUBLE;    sig[i++] = DBUS_TYPE_BOOLEAN; +  sig[i++] = DBUS_TYPE_BYTE; +  sig[i++] = DBUS_TYPE_BYTE; +  sig[i++] = DBUS_TYPE_NIL;    sig[i++] = DBUS_TYPE_ARRAY;    sig[i++] = DBUS_TYPE_UINT32;    sig[i++] = DBUS_TYPE_ARRAY; diff --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c index 2e942abc..37825f1c 100644 --- a/dbus/dbus-transport-unix.c +++ b/dbus/dbus-transport-unix.c @@ -717,11 +717,25 @@ unix_handle_watch (DBusTransport *transport,    _dbus_assert (watch == unix_transport->read_watch ||                  watch == unix_transport->write_watch); +  /* Disconnect in case of an error.  In case of hangup do not +   * disconnect the transport because data can still be in the buffer +   * and do_reading may need several iteration to read it all (because +   * of its max_bytes_read_per_iteration limit).  The condition where +   * flags == HANGUP (without READABLE) probably never happen in fact. +   */ +  if ((flags & DBUS_WATCH_ERROR) || +      ((flags & DBUS_WATCH_HANGUP) && !(flags & DBUS_WATCH_READABLE))) +    { +      _dbus_verbose ("Hang up or error on watch\n"); +      _dbus_transport_disconnect (transport); +      return TRUE; +    } +      if (watch == unix_transport->read_watch &&        (flags & DBUS_WATCH_READABLE))      { -#if 1 -      _dbus_verbose ("handling read watch\n"); +#if 0 +      _dbus_verbose ("handling read watch (%x)\n", flags);  #endif        if (!do_authentication (transport, TRUE, FALSE))          return FALSE; @@ -763,12 +777,6 @@ unix_handle_watch (DBusTransport *transport,      }  #endif /* DBUS_ENABLE_VERBOSE_MODE */ -  if (flags & (DBUS_WATCH_HANGUP | DBUS_WATCH_ERROR)) -    { -      _dbus_transport_disconnect (transport); -      return TRUE; -    } -      return TRUE;  } diff --git a/glib/Makefile.am b/glib/Makefile.am index d6f00d07..e0362b42 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -39,7 +39,7 @@ bin_PROGRAMS=dbus-glib-tool  dbus_glib_tool_SOURCES =			\  	dbus-glib-tool.c -dbus_glib_tool_LDADD= $(DBUS_GLIB_TOOL_LIBS) libdbus-gtool.la +dbus_glib_tool_LDADD= -lexpat libdbus-gtool.la  if DBUS_BUILD_TESTS diff --git a/test/data/invalid-config-files/not-well-formed.conf b/test/data/invalid-config-files/not-well-formed.conf new file mode 100644 index 00000000..9e59cbc0 --- /dev/null +++ b/test/data/invalid-config-files/not-well-formed.conf @@ -0,0 +1,5 @@ +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> +<busconfig> +  <user>mybususer</foo> +</busconfig> diff --git a/test/data/invalid-config-files/truncated-file.conf b/test/data/invalid-config-files/truncated-file.conf new file mode 100644 index 00000000..e8d60883 --- /dev/null +++ b/test/data/invalid-config-files/truncated-file.conf @@ -0,0 +1,9 @@ +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> +<busconfig> +  <user>mybususer</user> +  <listen>unix:path=/foo/bar</listen> +  <listen>tcp:port=1234</listen> +  <includedir>basic.d</includedir> +  <servicedir>/usr/share/foo</servicedir> +  <include ignore_missing="y | 
