diff options
author | Daniel Drake <dsd@gentoo.org> | 2008-03-20 21:07:00 +0000 |
---|---|---|
committer | Daniel Drake <dsd@gentoo.org> | 2008-03-20 21:19:48 +0000 |
commit | 88884ae4bbe721dac117d5190303cb67852fa5d3 (patch) | |
tree | 5e24d5208e5010e09c8554dbff61b59ddee6131b | |
parent | ead09cde6895df0034a685516987ce253575e9a7 (diff) | |
download | libusb-88884ae4bbe721dac117d5190303cb67852fa5d3.tar.gz |
Save transfer flags before invoking callback
The callback may free the transfer, in which case we can't read the flags
after it has returned.
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | libusb/io.c | 6 | ||||
-rw-r--r-- | libusb/libusb.h | 5 |
3 files changed, 9 insertions, 3 deletions
@@ -7,7 +7,6 @@ error codes fixme review review functionality missing over 0.1 endianness of control setup, issues when resubmitting transfers -interpreting transfer flags after callback returns is not safe rename poll to handle_events make libusb_get_pollfds return const? doxygen warnings diff --git a/libusb/io.c b/libusb/io.c index df5fe12..7900603 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -767,6 +767,7 @@ void usbi_handle_transfer_completion(struct usbi_transfer *itransfer, enum libusb_transfer_status status) { struct libusb_transfer *transfer = &itransfer->pub; + uint8_t flags; if (status == LIBUSB_TRANSFER_SILENT_COMPLETION) return; @@ -782,11 +783,14 @@ void usbi_handle_transfer_completion(struct usbi_transfer *itransfer, } } + flags = transfer->flags; transfer->status = status; transfer->actual_length = itransfer->transferred; if (transfer->callback) transfer->callback(transfer); - if (transfer->flags & LIBUSB_TRANSFER_FREE_TRANSFER) + /* transfer might have been freed by the above call, do not use from + * this point. */ + if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) libusb_free_transfer(transfer); } diff --git a/libusb/libusb.h b/libusb/libusb.h index f326afc..a306af9 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -521,7 +521,10 @@ enum libusb_transfer_flags { /** Automatically free() transfer buffer during libusb_free_transfer() */ LIBUSB_TRANSFER_FREE_BUFFER = 1<<1, - /** Automatically call libusb_free_transfer() after callback returns */ + /** Automatically call libusb_free_transfer() after callback returns. + * If this flag is set, it is illegal to call libusb_free_transfer() + * from your transfer callback, as this will result in a double-free + * when this flag is acted upon. */ LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2, }; |