From 88884ae4bbe721dac117d5190303cb67852fa5d3 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Thu, 20 Mar 2008 21:07:00 +0000 Subject: [PATCH] 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. --- TODO | 1 - libusb/io.c | 6 +++++- libusb/libusb.h | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 7282410..717bc8f 100644 --- a/TODO +++ b/TODO @@ -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, }; -- 2.7.4