gnutls: fix leaks
authorDan Winship <danw@gnome.org>
Mon, 4 Apr 2011 15:09:15 +0000 (11:09 -0400)
committerDan Winship <danw@gnome.org>
Sat, 9 Apr 2011 16:33:04 +0000 (12:33 -0400)
GTlsConnections were never being freed, due to circular refs.
Additionally, certificates seen during handshaking, and a
GSocketAddress used in the session cache code were being leaked.

tls/gnutls/gtlsclientconnection-gnutls.c
tls/gnutls/gtlsconnection-gnutls.c
tls/gnutls/gtlsinputstream-gnutls.c
tls/gnutls/gtlsoutputstream-gnutls.c

index 245fc09..2710e9c 100644 (file)
@@ -156,6 +156,7 @@ g_tls_client_connection_gnutls_constructed (GObject *object)
          gnutls->priv->session_id = g_strdup_printf ("%s/%d", addrstr, port);
          g_free (addrstr);
        }
+      g_object_unref (remote_addr);
     }
   g_object_unref (base_conn);
 
index c0fb898..b741184 100644 (file)
@@ -846,6 +846,8 @@ handshake_internal (GTlsConnectionGnutls  *gnutls,
          for (i = num_certs - 1; i >= 0; i--)
            {
              cert = g_tls_certificate_gnutls_new (&certs[i], chain);
+             if (chain)
+               g_object_unref (chain);
              chain = cert;
            }
        }
index dd22be5..6970883 100644 (file)
@@ -38,14 +38,18 @@ struct _GTlsInputStreamGnutlsPrivate
 };
 
 static void
-g_tls_input_stream_gnutls_finalize (GObject *object)
+g_tls_input_stream_gnutls_dispose (GObject *object)
 {
   GTlsInputStreamGnutls *stream = G_TLS_INPUT_STREAM_GNUTLS (object);
 
   if (stream->priv->conn)
-    g_object_unref (stream->priv->conn);
+    {
+      g_object_remove_weak_pointer (G_OBJECT (stream->priv->conn),
+                                   (gpointer *)&stream->priv->conn);
+      stream->priv->conn = NULL;
+    }
 
-  G_OBJECT_CLASS (g_tls_input_stream_gnutls_parent_class)->finalize (object);
+  G_OBJECT_CLASS (g_tls_input_stream_gnutls_parent_class)->dispose (object);
 }
 
 static gssize
@@ -57,6 +61,8 @@ g_tls_input_stream_gnutls_read (GInputStream  *stream,
 {
   GTlsInputStreamGnutls *tls_stream = G_TLS_INPUT_STREAM_GNUTLS (stream);
 
+  g_return_val_if_fail (tls_stream->priv->conn != NULL, -1);
+
   return g_tls_connection_gnutls_read (tls_stream->priv->conn,
                                       buffer, count, TRUE,
                                       cancellable, error);
@@ -117,6 +123,8 @@ g_tls_input_stream_gnutls_read_async (GInputStream        *stream,
   GError *error = NULL;
   GSource *source;
 
+  g_return_if_fail (tls_stream->priv->conn != NULL);
+
   simple = g_simple_async_result_new (G_OBJECT (stream), callback, user_data,
                                      g_tls_input_stream_gnutls_read_async);
   nread = g_tls_connection_gnutls_read (tls_stream->priv->conn,
@@ -168,6 +176,8 @@ g_tls_input_stream_gnutls_pollable_is_readable (GPollableInputStream *pollable)
 {
   GTlsInputStreamGnutls *tls_stream = G_TLS_INPUT_STREAM_GNUTLS (pollable);
 
+  g_return_val_if_fail (tls_stream->priv->conn != NULL, FALSE);
+
   return g_tls_connection_gnutls_check (tls_stream->priv->conn, G_IO_IN); 
 }
 
@@ -177,6 +187,8 @@ g_tls_input_stream_gnutls_pollable_create_source (GPollableInputStream *pollable
 {
   GTlsInputStreamGnutls *tls_stream = G_TLS_INPUT_STREAM_GNUTLS (pollable);
 
+  g_return_val_if_fail (tls_stream->priv->conn != NULL, NULL);
+
   return g_tls_connection_gnutls_create_source (tls_stream->priv->conn,
                                                G_IO_IN,
                                                cancellable);
@@ -203,7 +215,7 @@ g_tls_input_stream_gnutls_class_init (GTlsInputStreamGnutlsClass *klass)
 
   g_type_class_add_private (klass, sizeof (GTlsInputStreamGnutlsPrivate));
 
-  gobject_class->finalize = g_tls_input_stream_gnutls_finalize;
+  gobject_class->dispose = g_tls_input_stream_gnutls_dispose;
 
   input_stream_class->read_fn = g_tls_input_stream_gnutls_read;
   input_stream_class->read_async = g_tls_input_stream_gnutls_read_async;
@@ -230,6 +242,9 @@ g_tls_input_stream_gnutls_new (GTlsConnectionGnutls *conn)
   GTlsInputStreamGnutls *tls_stream;
 
   tls_stream = g_object_new (G_TYPE_TLS_INPUT_STREAM_GNUTLS, NULL);
-  tls_stream->priv->conn = g_object_ref (conn);
+  tls_stream->priv->conn = conn;
+  g_object_add_weak_pointer (G_OBJECT (conn),
+                            (gpointer *)&tls_stream->priv->conn);
+
   return G_INPUT_STREAM (tls_stream);
 }
index 462d74e..2e101e4 100644 (file)
@@ -38,14 +38,18 @@ struct _GTlsOutputStreamGnutlsPrivate
 };
 
 static void
-g_tls_output_stream_gnutls_finalize (GObject *object)
+g_tls_output_stream_gnutls_dispose (GObject *object)
 {
   GTlsOutputStreamGnutls *stream = G_TLS_OUTPUT_STREAM_GNUTLS (object);
 
   if (stream->priv->conn)
-    g_object_unref (stream->priv->conn);
+    {
+      g_object_remove_weak_pointer (G_OBJECT (stream->priv->conn),
+                                   (gpointer *)&stream->priv->conn);
+      stream->priv->conn = NULL;
+    }
 
-  G_OBJECT_CLASS (g_tls_output_stream_gnutls_parent_class)->finalize (object);
+  G_OBJECT_CLASS (g_tls_output_stream_gnutls_parent_class)->dispose (object);
 }
 
 static gssize
@@ -57,6 +61,8 @@ g_tls_output_stream_gnutls_write (GOutputStream  *stream,
 {
   GTlsOutputStreamGnutls *tls_stream = G_TLS_OUTPUT_STREAM_GNUTLS (stream);
 
+  g_return_val_if_fail (tls_stream->priv->conn != NULL, -1);
+
   return g_tls_connection_gnutls_write (tls_stream->priv->conn,
                                        buffer, count, TRUE,
                                        cancellable, error);
@@ -117,6 +123,8 @@ g_tls_output_stream_gnutls_write_async (GOutputStream        *stream,
   GError *error = NULL;
   GSource *source;
 
+  g_return_if_fail (tls_stream->priv->conn != NULL);
+
   simple = g_simple_async_result_new (G_OBJECT (stream), callback, user_data,
                                      g_tls_output_stream_gnutls_write_async);
   nwrote = g_tls_connection_gnutls_write (tls_stream->priv->conn,
@@ -168,6 +176,8 @@ g_tls_output_stream_gnutls_pollable_is_writable (GPollableOutputStream *pollable
 {
   GTlsOutputStreamGnutls *tls_stream = G_TLS_OUTPUT_STREAM_GNUTLS (pollable);
 
+  g_return_val_if_fail (tls_stream->priv->conn != NULL, FALSE);
+
   return g_tls_connection_gnutls_check (tls_stream->priv->conn, G_IO_OUT); 
 }
 
@@ -177,6 +187,8 @@ g_tls_output_stream_gnutls_pollable_create_source (GPollableOutputStream *pollab
 {
   GTlsOutputStreamGnutls *tls_stream = G_TLS_OUTPUT_STREAM_GNUTLS (pollable);
 
+  g_return_val_if_fail (tls_stream->priv->conn != NULL, NULL);
+
   return g_tls_connection_gnutls_create_source (tls_stream->priv->conn,
                                                G_IO_OUT,
                                                cancellable);
@@ -203,7 +215,7 @@ g_tls_output_stream_gnutls_class_init (GTlsOutputStreamGnutlsClass *klass)
 
   g_type_class_add_private (klass, sizeof (GTlsOutputStreamGnutlsPrivate));
 
-  gobject_class->finalize = g_tls_output_stream_gnutls_finalize;
+  gobject_class->dispose = g_tls_output_stream_gnutls_dispose;
 
   output_stream_class->write_fn = g_tls_output_stream_gnutls_write;
   output_stream_class->write_async = g_tls_output_stream_gnutls_write_async;
@@ -230,6 +242,9 @@ g_tls_output_stream_gnutls_new (GTlsConnectionGnutls *conn)
   GTlsOutputStreamGnutls *tls_stream;
 
   tls_stream = g_object_new (G_TYPE_TLS_OUTPUT_STREAM_GNUTLS, NULL);
-  tls_stream->priv->conn = g_object_ref (conn);
+  tls_stream->priv->conn = conn;
+  g_object_add_weak_pointer (G_OBJECT (conn),
+                            (gpointer *)&tls_stream->priv->conn);
+
   return G_OUTPUT_STREAM (tls_stream);
 }