[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#776142: unblock: libinfinity/0.6.5-1



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package libinfinity

libinfinity 0.6.5 contains multiple crash fixes. I'd feel much better if
those were included in the package. The diff is slightly noisy, but
mostly because of the new tarball (noise in the changelog, the
documentation output, and translations). A debdiff reduced to *.ac and
*.c changes is attached.

Changelog:

* Fix a crash when sending unsubscribe message causes connection failure
* InfdDirectory: Fail add-subdirectory request if name already exists
* Fix assertion failure when directory without storage is disposed
* Fix a memory leak in the plugin manager
* Make sure messages are not attempted to be sent on closed connections
* Add a missing status notify in InfXmppConnection
* Fix error message in server log when a client certificate is not
  trusted
* Fix possible memory corruption on insert in fixline buffer

Only relevant for FreeBSD and Mac OS X:

* Check whether we need -lresolv for res_query() (gobby #23)
* infinoted-plugin-document-stream: Only use MSG_NOSIGNAL if available
  (#7)
* inf-name-resolver: Include <arpa/nameser.h> and
  <arpa/nameser_compat.h>

unblock libinfinity/0.6.5-1
--- libinfinity-0.6.3/configure.ac	2014-10-09 19:28:17.794128998 +0200
+++ libinfinity-0.6.5/configure.ac	2015-01-18 02:14:02.575945693 +0100
@@ -1,4 +1,4 @@
-m4_define([libinfinity_version], [0.6.3])
+m4_define([libinfinity_version], [0.6.5])
 m4_define([libinfinity_api_version], [0.6])
 m4_define([libinfinity_libtool_version], [0:0:0])
 
@@ -125,7 +125,41 @@
 if test $platform = 'win32'; then
   infinity_LIBS="$infinity_LIBS -lws2_32 -ldnsapi"
 else
-  infinity_LIBS="$infinity_LIBS -lresolv"
+  # Check whether we need libresolv for res_query()
+  # Can't use AC_SEARCH_LIBS because res_query is a macro defined in
+  # resolv.h
+  AC_MSG_CHECKING(for res_query)
+  AC_TRY_LINK(
+    [
+      #include <sys/types.h>
+      #include <netinet/in.h>
+      #include <arpa/nameser.h>
+      #include <resolv.h>
+    ],
+    [res_query(NULL, 0, 0, NULL, 0);],
+    [
+      # res_init() available in libc
+      AC_MSG_RESULT(yes)
+    ],
+    [
+      LIBS="-lresolv"
+      AC_TRY_LINK(
+        [
+          #include <sys/types.h>
+          #include <netinet/in.h>
+          #include <arpa/nameser.h>
+          #include <resolv.h>
+        ],
+        [res_query(NULL, 0, 0, NULL, 0);],
+        [
+          AC_MSG_RESULT(in libresolv)
+          LIBS=""
+          infinity_LIBS="$infinity_LIBS -lresolv" # res_init available in libresolv
+        ],
+        [AC_MSG_ERROR(res_query not provided by either libc or libresolv)]
+      )
+    ]
+  )
 fi
 
 ###################################
--- libinfinity-0.6.3/infinoted/infinoted-plugin-manager.c	2014-08-29 16:48:38.249337739 +0200
+++ libinfinity-0.6.5/infinoted/infinoted-plugin-manager.c	2015-01-06 13:31:49.049584900 +0100
@@ -781,6 +781,8 @@
   g_hash_table_unref(priv->connections);
   g_hash_table_unref(priv->sessions);
 
+  g_free(priv->path);
+
   G_OBJECT_CLASS(parent_class)->finalize(object);
 }
 
--- libinfinity-0.6.3/infinoted/plugins/infinoted-plugin-certificate-auth.c	2014-08-29 16:48:38.253337778 +0200
+++ libinfinity-0.6.5/infinoted/plugins/infinoted-plugin-certificate-auth.c	2015-01-06 13:26:07.697569755 +0100
@@ -136,7 +136,7 @@
     if(res != GNUTLS_E_SUCCESS)
       inf_gnutls_set_error(&error, res);
     else if( (verify_result & GNUTLS_CERT_INVALID) != 0)
-      inf_gnutls_certificate_verification_set_error(&error, res);
+      inf_gnutls_certificate_verification_set_error(&error, verify_result);
 
     if(error != NULL)
     {
--- libinfinity-0.6.3/infinoted/plugins/infinoted-plugin-document-stream.c	2014-10-09 19:28:17.798128984 +0200
+++ libinfinity-0.6.5/infinoted/plugins/infinoted-plugin-document-stream.c	2015-01-18 02:14:02.575945693 +0100
@@ -40,6 +40,8 @@
 #include <string.h>
 #include <errno.h>
 
+#include "config.h"
+
 typedef enum _InfinotedPluginDocumentStreamStatus {
   INFINOTED_PLUGIN_DOCUMENT_STREAM_NORMAL,
   INFINOTED_PLUGIN_DOCUMENT_STREAM_RECEIVING,
@@ -882,7 +884,17 @@
 
   do
   {
-    bytes = send(stream->socket, data, len, MSG_NOSIGNAL);
+    bytes = send(
+      stream->socket,
+      data,
+      len,
+#ifdef HAVE_MSG_NOSIGNAL
+      MSG_NOSIGNAL
+#else
+      0
+#endif
+    );
+
     errcode = errno;
 
     if(bytes > 0)
@@ -990,7 +1002,11 @@
       stream->socket,
       stream->recv_queue.data + queue_offset,
       stream->recv_queue.alloc - queue_offset,
+#ifdef HAVE_MSG_NOSIGNAL
       MSG_NOSIGNAL
+#else
+      0
+#endif
     );
 
     errcode = errno;
--- libinfinity-0.6.3/libinfinity/client/infc-session-proxy.c	2014-08-29 16:48:38.265337895 +0200
+++ libinfinity-0.6.5/libinfinity/client/infc-session-proxy.c	2015-01-06 16:49:15.242110509 +0100
@@ -120,7 +120,11 @@
     );
   }
 
-  infc_session_proxy_release_connection(proxy);
+  /* If an error occurs while sending the "session-unsubscribe" message, the
+   * connection is released already as a result of the connection status
+   * notify handler, so we need another check here. */
+  if(priv->connection != NULL)
+    infc_session_proxy_release_connection(proxy);
 }
 
 /*
--- libinfinity-0.6.3/libinfinity/common/inf-error.c	2014-08-29 16:48:38.265337895 +0200
+++ libinfinity-0.6.5/libinfinity/common/inf-error.c	2015-01-06 13:26:07.709569755 +0100
@@ -359,6 +359,8 @@
       message = _("The certificate has expired");
     else if(verify & GNUTLS_CERT_INVALID)
       message = _("The certificate is invalid");
+    else
+      g_assert_not_reached();
 
     *error = g_error_new_literal(
       inf_gnutls_certificate_verification_error_quark(),
--- libinfinity-0.6.3/libinfinity/common/inf-name-resolver.c	2014-08-29 16:48:38.265337895 +0200
+++ libinfinity-0.6.5/libinfinity/common/inf-name-resolver.c	2015-01-06 13:26:07.709569755 +0100
@@ -61,6 +61,8 @@
 # include <windns.h>
 #else
 # include <resolv.h>
+# include <arpa/nameser.h>
+# include <arpa/nameser_compat.h>
 #endif
 
 #include <errno.h>
--- libinfinity-0.6.3/libinfinity/common/inf-xmpp-connection.c	2014-08-29 16:48:38.269337933 +0200
+++ libinfinity-0.6.5/libinfinity/common/inf-xmpp-connection.c	2015-01-06 13:26:07.709569755 +0100
@@ -723,6 +723,7 @@
        * disconnection callback because we wanted to keep the gnutls context
        * alive until gnutls_record_send() returns. */
       inf_xmpp_connection_clear(xmpp);
+      g_object_notify(G_OBJECT(xmpp), "status");
     }
   }
 }
@@ -3328,6 +3329,8 @@
        * signal handler) then we can't delete the XML parser here (otherwise
        * libxml2 crashes, understandably). Instead, just set the status to
        * closed and clean up after XML parsing in _received_cb(). */
+      /* TODO: We should do the full cleanup here, and _received_cb() and
+       * send_chars should copy/ref everything they need on the stack. */
       if(priv->parsing == 0)
         inf_xmpp_connection_clear(xmpp);
 
--- libinfinity-0.6.3/libinfinity/communication/inf-communication-central-method.c	2014-08-29 16:48:38.269337933 +0200
+++ libinfinity-0.6.5/libinfinity/communication/inf-communication-central-method.c	2015-01-06 13:26:07.709569755 +0100
@@ -57,6 +57,85 @@
 static GObjectClass* parent_class;
 
 static void
+inf_communication_central_method_broadcast(InfCommunicationMethod* method,
+                                           xmlNodePtr xml,
+                                           InfXmlConnection* except)
+{
+  InfCommunicationCentralMethodPrivate* priv;
+  InfCommunicationRegistry* registry;
+  InfCommunicationGroup* group;
+  GSList* connections;
+  GSList* item;
+  InfXmlConnection* connection;
+  gboolean is_registered;
+  InfXmlConnectionStatus status;
+
+  priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method);
+
+  /* Each of the inf_communication_registry_send() calls can do a callback
+   * which might possibly screw up our connection list completely. So be safe
+   * here by copying all relevant information on the stack. */
+  g_object_ref(method);
+  registry = g_object_ref(priv->registry);
+  group = g_object_ref(priv->group);
+
+  connections = g_slist_copy(priv->connections);
+  for(item = connections; item != NULL; item = item->next)
+    g_object_ref(item->data);
+
+  while(connections)
+  {
+    connection = INF_XML_CONNECTION(connections->data);
+
+    /* A callback from a prior iteration might have unregistered the
+     * connection. */
+    is_registered = inf_communication_registry_is_registered(
+      registry,
+      group,
+      connection
+    );
+
+    /* in case our remove member was not yet called we also check the
+     * status here, i.e. if we are called in response to a handler of the
+     * notify::status signal that ran before ours. */
+    g_object_get(G_OBJECT(connection), "status", &status, NULL);
+    if(is_registered &&
+       status == INF_XML_CONNECTION_OPEN &&
+       connection != except)
+    {
+      if(connections->next != NULL)
+      {
+        /* Keep ownership of XML if there might be more connections we should
+         * send it to. */
+        inf_communication_registry_send(
+          registry,
+          group,
+          connection,
+          xmlCopyNode(xml, 1)
+        );
+      }
+      else
+      {
+        /* Pass ownership of XML if this is definitely the last connection
+         * in the list. */
+        inf_communication_registry_send(registry, group, connection, xml);
+        xml = NULL;
+      }
+    }
+
+    g_object_unref(connection);
+    connections = g_slist_delete_link(connections, connections);
+  }
+
+  g_object_unref(method);
+  g_object_unref(registry);
+  g_object_unref(group);
+
+  if(xml != NULL)
+    xmlFreeNode(xml);
+}
+
+static void
 inf_communication_central_method_notify_status_cb(GObject* object,
                                                   GParamSpec* pspec,
                                                   gpointer user_data)
@@ -204,71 +283,7 @@
 inf_communication_central_method_send_all(InfCommunicationMethod* method,
                                           xmlNodePtr xml)
 {
-  InfCommunicationCentralMethodPrivate* priv;
-  InfCommunicationRegistry* registry;
-  InfCommunicationGroup* group;
-  GSList* connections;
-  GSList* item;
-  InfXmlConnection* connection;
-  gboolean is_registered;
-
-  priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method);
-
-  /* Each of the inf_communication_registry_send() calls can do a callback
-   * which might possibly screw up our connection list completely. So be safe
-   * here by copying all relevant information on the stack. */
-  g_object_ref(method);
-  registry = g_object_ref(priv->registry);
-  group = g_object_ref(priv->group);
-
-  connections = g_slist_copy(priv->connections);
-  for(item = connections; item != NULL; item = item->next)
-    g_object_ref(item->data);
-
-  while(connections)
-  {
-    connection = INF_XML_CONNECTION(connections->data);
-
-    /* A callback from a prior iteration might have unregistered the
-     * connection. */
-    is_registered = inf_communication_registry_is_registered(
-      registry,
-      group,
-      connection
-    );
-
-    if(is_registered)
-    {
-      if(connections->next != NULL)
-      {
-        /* Keep ownership of XML if there might be more connections we should
-         * send it to. */
-        inf_communication_registry_send(
-          registry,
-          group,
-          connection,
-          xmlCopyNode(xml, 1)
-        );
-      }
-      else
-      {
-        /* Pass ownership of XML if this is definitely the last connection
-         * in the list. */
-        inf_communication_registry_send(registry, group, connection, xml);
-        xml = NULL;
-      }
-    }
-
-    g_object_unref(connection);
-    connections = g_slist_delete_link(connections, connections);
-  }
-
-  g_object_unref(method);
-  g_object_unref(registry);
-  g_object_unref(group);
-
-  if(xml != NULL)
-    xmlFreeNode(xml);
+  inf_communication_central_method_broadcast(method, xml, NULL);
 }
 
 static void
@@ -319,18 +334,11 @@
 
     if(priv->is_publisher && scope == INF_COMMUNICATION_SCOPE_GROUP)
     {
-      for(item = priv->connections; item != NULL; item = item->next)
-      {
-        if(item->data != connection)
-        {
-          inf_communication_registry_send(
-            priv->registry,
-            priv->group,
-            INF_XML_CONNECTION(item->data),
-            xmlCopyNode(xml, 1)
-          );
-        }
-      }
+      inf_communication_central_method_broadcast(
+        method,
+        xmlCopyNode(xml, 1),
+        connection
+      );
     }
 
     g_object_unref(method);
--- libinfinity-0.6.3/libinfinity/communication/inf-communication-registry.c	2014-08-29 16:48:38.273337971 +0200
+++ libinfinity-0.6.5/libinfinity/communication/inf-communication-registry.c	2015-01-06 13:26:07.713569755 +0100
@@ -100,6 +100,9 @@
 inf_communication_registry_send_real(InfCommunicationRegistryEntry* entry,
                                      guint num_messages)
 {
+  InfXmlConnection* connection;
+  InfXmlConnectionStatus status;
+
   xmlNodePtr container;
   xmlNodePtr child;
   xmlNodePtr xml;
@@ -140,6 +143,12 @@
     entry->enqueued_list = container;
     child = container;
 
+    connection = entry->key.connection;
+    g_object_ref(connection);
+
+    g_object_get(G_OBJECT(connection), "status", &status, NULL);
+    g_assert(status == INF_XML_CONNECTION_OPEN);
+
     while(child != NULL)
     {
       /* TODO: The group could be unset at this point if called from
@@ -151,11 +160,7 @@
       {
         for(xml = child->children; xml != NULL; xml = xml->next)
         {
-          inf_communication_method_enqueued(
-            entry->method,
-            entry->key.connection,
-            xml
-          );
+          inf_communication_method_enqueued(entry->method, connection, xml);
         }
       }
 
@@ -174,8 +179,15 @@
        * will simply append to entry->enqueued_list, and we will enqueue and
        * send the messages within the next iteration(s).
        */
-      inf_xml_connection_send(entry->key.connection, xml);
+      inf_xml_connection_send(connection, xml);
+
+      /* Break if sending the data lead to connection closure */
+      g_object_get(G_OBJECT(connection), "status", &status, NULL);
+      if(status != INF_XML_CONNECTION_OPEN)
+        break;
     }
+
+    g_object_unref(connection);
   }
 }
 
--- libinfinity-0.6.3/libinfinity/server/infd-directory.c	2014-10-09 19:28:17.802128969 +0200
+++ libinfinity-0.6.5/libinfinity/server/infd-directory.c	2015-01-06 14:14:35.489698772 +0100
@@ -4471,6 +4471,7 @@
   InfdDirectoryNode* node;
   gboolean result;
   gchar* path;
+  GError* local_error;
 
   InfBrowserIter parent_iter;
   InfBrowserIter iter;
@@ -4481,11 +4482,17 @@
 
   priv = INFD_DIRECTORY_PRIVATE(directory);
 
-  if(!infd_directory_node_is_name_available(directory, parent, name, error))
-  {
-    return NULL;
-  }
-  else
+  local_error = NULL;
+  node = NULL;
+
+  infd_directory_node_is_name_available(
+    directory,
+    parent,
+    name,
+    &local_error
+  );
+
+  if(local_error == NULL)
   {
     infd_directory_node_make_path(parent, name, &path, NULL);
 
@@ -4495,37 +4502,46 @@
       result = TRUE;
 
     g_free(path);
-    if(result == FALSE) return NULL;
+    if(result == TRUE)
+    {
+      node = infd_directory_node_new_subdirectory(
+        directory,
+        parent,
+        priv->node_counter++,
+        g_strdup(name),
+        sheet_set,
+        TRUE
+      );
 
-    node = infd_directory_node_new_subdirectory(
-      directory,
-      parent,
-      priv->node_counter++,
-      g_strdup(name),
-      sheet_set,
-      TRUE
-    );
+      node->shared.subdir.explored = TRUE;
 
-    node->shared.subdir.explored = TRUE;
+      infd_directory_node_register(directory, node, request, NULL, seq);
 
-    infd_directory_node_register(directory, node, request, NULL, seq);
+      parent_iter.node_id = parent->id;
+      parent_iter.node = parent;
+      iter.node_id = node->id;
+      iter.node = node;
 
-    parent_iter.node_id = parent->id;
-    parent_iter.node = parent;
-    iter.node_id = node->id;
-    iter.node = node;
+      inf_request_finish(
+        INF_REQUEST(request),
+        inf_request_result_make_add_node(
+          INF_BROWSER(directory),
+          &parent_iter,
+          &iter
+        )
+      );
+    }
+  }
 
-    inf_request_finish(
-      INF_REQUEST(request),
-      inf_request_result_make_add_node(
-        INF_BROWSER(directory),
-        &parent_iter,
-        &iter
-      )
-    );
+  if(local_error != NULL)
+  {
+    g_assert(node == NULL);
 
-    return node;
+    inf_request_fail(INF_REQUEST(request), local_error);
+    g_propagate_error(error, local_error);
   }
+
+  return node;
 }
 
 static gboolean
@@ -8568,9 +8584,12 @@
   infd_directory_node_free(directory, priv->root);
   priv->root = NULL;
 
-  g_assert(priv->orig_root_acl != NULL);
-  inf_acl_sheet_set_free(priv->orig_root_acl);
-  priv->orig_root_acl = NULL;
+  /* Can be NULL, for example when no storage is set */
+  if(priv->orig_root_acl != NULL)
+  {
+    inf_acl_sheet_set_free(priv->orig_root_acl);
+    priv->orig_root_acl = NULL;
+  }
 
   g_hash_table_destroy(priv->nodes);
   priv->nodes = NULL;
--- libinfinity-0.6.3/libinftext/inf-text-fixline-buffer.c	2014-08-29 16:48:38.277338010 +0200
+++ libinfinity-0.6.5/libinftext/inf-text-fixline-buffer.c	2015-01-06 13:26:07.717569756 +0100
@@ -1181,7 +1181,11 @@
       ((guint)priv->n_keep - (pos - buf_len)) * sizeof(guint)
     );
 
-    priv->keep = g_realloc(priv->keep, (pos - buf_len) * sizeof(guint));
+    priv->keep = g_realloc(
+      priv->keep,
+      ((guint)priv->n_keep - (pos - buf_len)) * sizeof(guint)
+    );
+
     priv->n_keep -= (pos - buf_len);
 
     inf_text_buffer_insert_chunk(priv->buffer, buf_len, new_chunk, user);
--- libinfinity-0.6.3/test/inf-test-text-fixline.c	2014-08-29 16:48:38.281338048 +0200
+++ libinfinity-0.6.5/test/inf-test-text-fixline.c	2015-01-06 13:26:07.721569756 +0100
@@ -251,6 +251,8 @@
     { "\n\n\n\n", "\n\n", 2, MKBUFINOP(3, "A"), "\n\n\nA\n", "\n\n\nA\n\n" },
     { "\n\n\n\n", "\n\n", 2, MKBUFINOP(4, "A"), "\n\n\n\nA", "\n\n\n\nA\n\n" },
 
+    { "\n\n\n\n\n", "\n\n", 2, MKBUFINOP(3, "A"), "\n\n\nA\n\n", "\n\n\nA\n\n" },
+
     /* 18: */
     { "", "\n\n", 2, MKBASEDLOP(0, 1), "", "\n\n" },
     { "", "\n\n", 2, MKBASEDLOP(1, 1), "", "\n\n" },

Reply to: