diff options
author | FTDI Dev <jenkins@ftdichip.com> | 2016-03-02 16:29:27 +0000 |
---|---|---|
committer | Chris Dickens <christopher.a.dickens@gmail.com> | 2016-05-29 19:56:17 -0700 |
commit | adb6e39b68699b5d849836f9aaff7640b0f16173 (patch) | |
tree | 47db3eab0eff3fe3c48f8c633d204f9456e898bb | |
parent | ad6f23480ecfbe10a34a78afde58fdac32d3e457 (diff) | |
download | libusb-adb6e39b68699b5d849836f9aaff7640b0f16173.tar.gz |
Clean failure in discovered_devs_append.
Closes #161
Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
-rw-r--r-- | libusb/core.c | 40 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
2 files changed, 25 insertions, 17 deletions
diff --git a/libusb/core.c b/libusb/core.c index d57edad..54c1010 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -627,6 +627,16 @@ static struct discovered_devs *discovered_devs_alloc(void) return ret; } +static void discovered_devs_free(struct discovered_devs *discdevs) +{ + size_t i; + + for (i = 0; i < discdevs->len; i++) + libusb_unref_device(discdevs->devices[i]); + + free(discdevs); +} + /* append a device to the discovered devices collection. may realloc itself, * returning new discdevs. returns NULL on realloc failure. */ struct discovered_devs *discovered_devs_append( @@ -634,6 +644,7 @@ struct discovered_devs *discovered_devs_append( { size_t len = discdevs->len; size_t capacity; + struct discovered_devs *new_discdevs; /* if there is space, just append the device */ if (len < discdevs->capacity) { @@ -645,25 +656,21 @@ struct discovered_devs *discovered_devs_append( /* exceeded capacity, need to grow */ usbi_dbg("need to increase capacity"); capacity = discdevs->capacity + DISCOVERED_DEVICES_SIZE_STEP; - discdevs = usbi_reallocf(discdevs, + /* can't use usbi_reallocf here because in failure cases it would + * free the existing discdevs without unreferencing its devices. */ + new_discdevs = realloc(discdevs, sizeof(*discdevs) + (sizeof(void *) * capacity)); - if (discdevs) { - discdevs->capacity = capacity; - discdevs->devices[len] = libusb_ref_device(dev); - discdevs->len++; + if (!new_discdevs) { + discovered_devs_free(discdevs); + return NULL; } - return discdevs; -} - -static void discovered_devs_free(struct discovered_devs *discdevs) -{ - size_t i; - - for (i = 0; i < discdevs->len; i++) - libusb_unref_device(discdevs->devices[i]); + discdevs = new_discdevs; + discdevs->capacity = capacity; + discdevs->devices[len] = libusb_ref_device(dev); + discdevs->len++; - free(discdevs); + return discdevs; } /* Allocate a new device with a specific session ID. The returned device has @@ -854,7 +861,8 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, *list = ret; out: - discovered_devs_free(discdevs); + if (discdevs) + discovered_devs_free(discdevs); return len; } diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 17cd90c..9e02ae0 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11112 +#define LIBUSB_NANO 11113 |