email plugin: Fix freeing linked lists.
authorFlorian Forster <octo@collectd.org>
Wed, 17 Jun 2015 08:37:31 +0000 (10:37 +0200)
committerFlorian Forster <octo@collectd.org>
Wed, 17 Jun 2015 08:37:31 +0000 (10:37 +0200)
The previous code essentially did:

    for (…; …; ptr = ptr->next)
      free (ptr);

The "ptr->next" is a use-after-free.

src/email.c

index 8f633cd..4aac3e3 100644 (file)
@@ -570,10 +570,27 @@ static int email_init (void)
        return (0);
 } /* int email_init */
 
-static int email_shutdown (void)
+static void type_list_free (type_list_t *t)
 {
-       type_t *ptr = NULL;
+       type_t *this;
+
+       this = t->head;
+       while (this != NULL)
+       {
+               type_t *next = this->next;
+
+               sfree (this->name);
+               sfree (this);
+
+               this = next;
+       }
 
+       t->head = NULL;
+       t->tail = NULL;
+}
+
+static int email_shutdown (void)
+{
        int i = 0;
 
        if (connector != ((pthread_t) 0)) {
@@ -613,35 +630,12 @@ static int email_shutdown (void)
 
        pthread_mutex_unlock (&conns_mutex);
 
-       for (ptr = list_count.head; NULL != ptr; ptr = ptr->next) {
-               free (ptr->name);
-               free (ptr);
-       }
-
-       for (ptr = list_count_copy.head; NULL != ptr; ptr = ptr->next) {
-               free (ptr->name);
-               free (ptr);
-       }
-
-       for (ptr = list_size.head; NULL != ptr; ptr = ptr->next) {
-               free (ptr->name);
-               free (ptr);
-       }
-
-       for (ptr = list_size_copy.head; NULL != ptr; ptr = ptr->next) {
-               free (ptr->name);
-               free (ptr);
-       }
-
-       for (ptr = list_check.head; NULL != ptr; ptr = ptr->next) {
-               free (ptr->name);
-               free (ptr);
-       }
-
-       for (ptr = list_check_copy.head; NULL != ptr; ptr = ptr->next) {
-               free (ptr->name);
-               free (ptr);
-       }
+       type_list_free (&list_count);
+       type_list_free (&list_count_copy);
+       type_list_free (&list_size);
+       type_list_free (&list_size_copy);
+       type_list_free (&list_check);
+       type_list_free (&list_check_copy);
 
        unlink ((NULL == sock_file) ? SOCK_PATH : sock_file);