gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r30849 - gnunet/src/set


From: gnunet
Subject: [GNUnet-SVN] r30849 - gnunet/src/set
Date: Fri, 22 Nov 2013 18:42:04 +0100

Author: dold
Date: 2013-11-22 18:42:03 +0100 (Fri, 22 Nov 2013)
New Revision: 30849

Modified:
   gnunet/src/set/set_api.c
Log:
fixed a bug where a set handle was used after free


Modified: gnunet/src/set/set_api.c
===================================================================
--- gnunet/src/set/set_api.c    2013-11-22 13:43:13 UTC (rev 30848)
+++ gnunet/src/set/set_api.c    2013-11-22 17:42:03 UTC (rev 30849)
@@ -362,6 +362,85 @@
 }
 
 
+/**
+ * Destroy the set handle if no operations are left, mark the set
+ * for destruction otherwise.
+ *
+ * @param set set handle to destroy
+ */
+static int
+set_destroy (struct GNUNET_SET_Handle *set)
+{
+  if (NULL != set->ops_head)
+  {
+    set->destroy_requested = GNUNET_YES;
+    return GNUNET_NO;
+  }
+  GNUNET_CLIENT_disconnect (set->client);
+  set->client = NULL;
+  GNUNET_MQ_destroy (set->mq);
+  set->mq = NULL;
+  GNUNET_free (set);
+  return GNUNET_YES;
+}
+
+
+
+
+/**
+ * Cancel the given set operation.  We need to send an explicit cancel message,
+ * as all operations one one set communicate using one handle.
+ *
+ * In contrast to GNUNET_SET_operation_cancel, this function indicates whether
+ * the set of the operation has been destroyed because all operations are done 
and
+ * the set's destruction was requested before.
+ *
+ * @param oh set operation to cancel
+ * @return GNUNET_YES if the set of the operation was destroyed
+ */
+static int
+set_operation_cancel (struct GNUNET_SET_OperationHandle *oh)
+{
+  int ret = GNUNET_NO;
+
+  if (NULL != oh->conclude_mqm)
+    GNUNET_MQ_discard (oh->conclude_mqm);
+
+  /* is the operation already commited? */
+  if (NULL != oh->set)
+  {
+    struct GNUNET_SET_OperationHandle *h_assoc;
+    struct GNUNET_MQ_Envelope *mqm;
+
+    GNUNET_CONTAINER_DLL_remove (oh->set->ops_head, oh->set->ops_tail, oh);
+    h_assoc = GNUNET_MQ_assoc_remove (oh->set->mq, oh->request_id);
+    GNUNET_assert ((h_assoc == NULL) || (h_assoc == oh));
+    mqm = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_CANCEL);
+    GNUNET_MQ_send (oh->set->mq, mqm);
+
+    if (GNUNET_YES == oh->set->destroy_requested)
+      ret = set_destroy (oh->set);
+  }
+
+  GNUNET_free (oh);
+  
+  return ret;
+}
+
+
+/**
+ * Cancel the given set operation.  We need to send an explicit cancel message,
+ * as all operations one one set communicate using one handle.
+ *
+ * @param oh set operation to cancel
+ */
+void
+GNUNET_SET_operation_cancel (struct GNUNET_SET_OperationHandle *oh)
+{
+  (void) set_operation_cancel (oh);
+}
+
+
 static void
 handle_client_set_error (void *cls, enum GNUNET_MQ_Error error)
 {
@@ -372,9 +451,9 @@
     if (NULL != set->ops_head->result_cb)
       set->ops_head->result_cb (set->ops_head->result_cls, NULL,
                                 GNUNET_SET_STATUS_FAILURE);
-    GNUNET_SET_operation_cancel (set->ops_head);
+    if (GNUNET_YES == set_operation_cancel (set->ops_head))
+      return; /* stop if the set is destroyed */
   }
-
   set->invalid = GNUNET_YES;
 }
 
@@ -496,20 +575,13 @@
 
 /**
  * Destroy the set handle, and free all associated resources.
+ *
+ * @param set set handle to destroy
  */
 void
 GNUNET_SET_destroy (struct GNUNET_SET_Handle *set)
 {
-  if (NULL != set->ops_head)
-  {
-    set->destroy_requested = GNUNET_YES;
-    return;
-  }
-  GNUNET_CLIENT_disconnect (set->client);
-  set->client = NULL;
-  GNUNET_MQ_destroy (set->mq);
-  set->mq = NULL;
-  GNUNET_free (set);
+  (void) set_destroy (set);
 }
 
 
@@ -689,38 +761,6 @@
 
 
 /**
- * Cancel the given set operation.  We need to send an explicit cancel message,
- * as all operations one one set communicate using one handle.
- *
- * @param oh set operation to cancel
- */
-void
-GNUNET_SET_operation_cancel (struct GNUNET_SET_OperationHandle *oh)
-{
-  if (NULL != oh->conclude_mqm)
-    GNUNET_MQ_discard (oh->conclude_mqm);
-
-  /* is the operation already commited? */
-  if (NULL != oh->set)
-  {
-    struct GNUNET_SET_OperationHandle *h_assoc;
-    struct GNUNET_MQ_Envelope *mqm;
-
-    GNUNET_CONTAINER_DLL_remove (oh->set->ops_head, oh->set->ops_tail, oh);
-    h_assoc = GNUNET_MQ_assoc_remove (oh->set->mq, oh->request_id);
-    GNUNET_assert ((h_assoc == NULL) || (h_assoc == oh));
-    mqm = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_CANCEL);
-    GNUNET_MQ_send (oh->set->mq, mqm);
-
-    if (GNUNET_YES == oh->set->destroy_requested)
-      GNUNET_SET_destroy (oh->set);
-  }
-
-  GNUNET_free (oh);
-}
-
-
-/**
  * Commit a set to be used with a set operation.
  * This function is called once we have fully constructed
  * the set that we want to use for the operation.  At this




reply via email to

[Prev in Thread] Current Thread [Next in Thread]