libftdi Archives

Subject: libftdi-1.0: Reduce memory leaks

From: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
To: libftdi@xxxxxxxxxxxxxxxxxxxxxxx
Date: Mon, 7 Jun 2010 19:02:30 +0200
Hello,

libusb_init() requires libusb_exit() to free all memory. I placed this call
in ftdi_free(). libusb_get_device_list() also requires a
libusb_free_device_list(). This free must happen after an libusb_open() and
in all the error pathes, so I added a define for the error case and the return 
of
the libusb_open() call must be remembered.

Bye
-- 
Uwe Bonnes                bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Institut fuer Kernphysik  Schlossgartenstrasse 9  64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------
>From 01c5ddd2ebf902257e815154ce5bd464899d8969 Mon Sep 17 00:00:00 2001
From: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 7 Jun 2010 19:00:42 +0200
Subject: Call libusb_exit() and libusb_free_device_list() to avoid leaks

---
 src/ftdi.c |   36 +++++++++++++++++++++++++-----------
 1 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/src/ftdi.c b/src/ftdi.c
index 7b4b987..1e34f47 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -41,6 +41,12 @@
         return code;                       \
    } while(0);
 
+#define ftdi_error_return_free_device_list(code, str, devs) do {    \
+        libusb_free_device_list(devs,1);   \
+        ftdi->error_str = str;             \
+        return code;                       \
+   } while(0);
+
 
 /**
     Internal function to close usb device pointer.
@@ -195,6 +201,7 @@ void ftdi_deinit(struct ftdi_context *ftdi)
 void ftdi_free(struct ftdi_context *ftdi)
 {
     ftdi_deinit(ftdi);
+    libusb_exit(NULL);
     free(ftdi);
 }
 
@@ -250,13 +257,13 @@ int ftdi_usb_find_all(struct ftdi_context *ftdi, struct 
ftdi_device_list **devli
         struct libusb_device_descriptor desc;
 
         if (libusb_get_device_descriptor(dev, &desc) < 0)
-            ftdi_error_return(-6, "libusb_get_device_descriptor() failed");
+            ftdi_error_return_free_device_list(-6, 
"libusb_get_device_descriptor() failed", devs);
 
         if (desc.idVendor == vendor && desc.idProduct == product)
         {
             *curdev = (struct ftdi_device_list*)malloc(sizeof(struct 
ftdi_device_list));
             if (!*curdev)
-                ftdi_error_return(-3, "out of memory");
+                ftdi_error_return_free_device_list(-3, "out of memory", devs);
              
             (*curdev)->next = NULL;
             (*curdev)->dev = dev;
@@ -265,7 +272,7 @@ int ftdi_usb_find_all(struct ftdi_context *ftdi, struct 
ftdi_device_list **devli
             count++;
         }
     }
-
+    libusb_free_device_list(devs,1);
     return count;
 }
 
@@ -621,6 +628,7 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int 
vendor, int product,
     libusb_device **devs;
     char string[256];
     int i = 0;
+    int res;
 
     if (libusb_init(NULL) < 0)
         ftdi_error_return(-11, "libusb_init() failed");
@@ -636,19 +644,19 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, 
int vendor, int product,
         struct libusb_device_descriptor desc;
 
         if (libusb_get_device_descriptor(dev, &desc) < 0)
-            ftdi_error_return(-13, "libusb_get_device_descriptor() failed");
+            ftdi_error_return_free_device_list(-13, 
"libusb_get_device_descriptor() failed", devs);
 
         if (desc.idVendor == vendor && desc.idProduct == product)
         {
             if (libusb_open(dev, &ftdi->usb_dev) < 0)
-                ftdi_error_return(-4, "usb_open() failed");
+                ftdi_error_return_free_device_list(-4, "usb_open() failed", 
devs);
 
             if (description != NULL)
             {
                 if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, 
desc.iProduct, (unsigned char *)string, sizeof(string)) < 0)
                 {
                     libusb_close (ftdi->usb_dev);
-                    ftdi_error_return(-8, "unable to fetch product 
description");
+                    ftdi_error_return_free_device_list(-8, "unable to fetch 
product description", devs);
                 }
                 if (strncmp(string, description, sizeof(string)) != 0)
                 {
@@ -661,7 +669,7 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int 
vendor, int product,
                 if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, 
desc.iSerialNumber, (unsigned char *)string, sizeof(string)) < 0)
                 {
                     ftdi_usb_close_internal (ftdi);
-                    ftdi_error_return(-9, "unable to fetch serial number");
+                    ftdi_error_return_free_device_list(-9, "unable to fetch 
serial number", devs);
                 }
                 if (strncmp(string, serial, sizeof(string)) != 0)
                 {
@@ -678,12 +686,14 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, 
int vendor, int product,
                     continue;
                 }
 
-            return ftdi_usb_open_dev(ftdi, dev);
+            res = ftdi_usb_open_dev(ftdi, dev);
+            libusb_free_device_list(devs, 1);
+            return res;
         }
     }
 
     // device not found
-    ftdi_error_return(-3, "device not found");
+    ftdi_error_return_free_device_list(-3, "device not found", devs);
 }
 
 /**
@@ -742,11 +752,15 @@ int ftdi_usb_open_string(struct ftdi_context *ftdi, const 
char* description)
         {
            if (bus_number == libusb_get_bus_number (dev)
                && device_address == libusb_get_device_address (dev))
-                return ftdi_usb_open_dev(ftdi, dev);
+            {
+                int res = ftdi_usb_open_dev(ftdi, dev);
+                libusb_free_device_list(devs, 1);
+                return res;
+            }
         }
 
         // device not found
-        ftdi_error_return(-3, "device not found");
+        ftdi_error_return_free_device_list(-3, "device not found", devs);
     }
     else if (description[0] == 'i' || description[0] == 's')
     {
-- 
1.6.4.2



--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx   

Current Thread