summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPete Batard <pbatard@gmail.com>2010-03-22 01:18:16 +0000
committerPete Batard <pbatard@gmail.com>2010-03-22 01:18:16 +0000
commitad262a68bb58b86a1ae6e2d6b3cce2d847cd3d9b (patch)
tree36091bbb5edafd71703e5ac0e6a0a0ff64821195
parentae3a15f6b69a15f1940c47a8fc698396f6cc4d06 (diff)
downloadlibusb-ad262a68bb58b86a1ae6e2d6b3cce2d847cd3d9b.tar.gz
fixed double freeing of fds (reported by Travis Robinson)r224
-rw-r--r--libusb/os/poll_windows.c12
-rw-r--r--libusb/os/windows_usb.c4
2 files changed, 9 insertions, 7 deletions
diff --git a/libusb/os/poll_windows.c b/libusb/os/poll_windows.c
index 6fdf4b5..fe27d53 100644
--- a/libusb/os/poll_windows.c
+++ b/libusb/os/poll_windows.c
@@ -613,6 +613,8 @@ int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
}
index = _fd_to_index_and_lock(fds[i].fd);
+ poll_dbg("fd[%d]=%d: (overlapped=%p) got events %04X", i, poll_fd[index].fd, poll_fd[index].overlapped, fds[i].events);
+
if ( (index < 0) || (poll_fd[index].handle == INVALID_HANDLE_VALUE)
|| (poll_fd[index].handle == 0) || (poll_fd[index].overlapped == NULL)) {
fds[i].revents |= POLLNVAL | POLLERR;
@@ -629,7 +631,7 @@ int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
if ((fds[i].events & POLLIN) && (poll_fd[index].rw != RW_READ)) {
fds[i].revents |= POLLNVAL | POLLERR;
errno = EBADF;
- usbi_warn(NULL, "attempted POLLIN on fd[%d] without READ access", i);
+ usbi_warn(NULL, "attempted POLLIN on fd without READ access");
LeaveCriticalSection(&_poll_fd[index].mutex);
triggered = -1;
goto poll_exit;
@@ -638,14 +640,12 @@ int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
if ((fds[i].events & POLLOUT) && (poll_fd[index].rw != RW_WRITE)) {
fds[i].revents |= POLLNVAL | POLLERR;
errno = EBADF;
- usbi_warn(NULL, "attempted POLLOUT on fd[%d] without WRITE access", i);
+ usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access");
LeaveCriticalSection(&_poll_fd[index].mutex);
triggered = -1;
goto poll_exit;
}
- poll_dbg("fd[%d]=%d (overlapped = %p) got events %04X", i, poll_fd[index].fd, poll_fd[index].overlapped, fds[i].events);
-
// The following macro only works if overlapped I/O was reported pending
if ( (HasOverlappedIoCompleted(poll_fd[index].overlapped))
|| (HasOverlappedIoCompletedSync(poll_fd[index].overlapped)) ) {
@@ -805,7 +805,7 @@ ssize_t usbi_write(int fd, const void *buf, size_t count)
return -1;
}
- poll_dbg("set pipe event (thread = %08X)", GetCurrentThreadId());
+ poll_dbg("set pipe event (fd = %d, thread = %08X)", index, GetCurrentThreadId());
SetEvent(poll_fd[index].overlapped->hEvent);
poll_fd[index].overlapped->Internal = STATUS_WAIT_0;
// If two threads write on the pipe at the same time, we need to
@@ -844,7 +844,7 @@ ssize_t usbi_read(int fd, void *buf, size_t count)
goto out;
}
- poll_dbg("clr pipe event (thread = %08X)", GetCurrentThreadId());
+ poll_dbg("clr pipe event (fd = %d, thread = %08X)", index, GetCurrentThreadId());
poll_fd[index].overlapped->InternalHigh--;
// Don't reset unless we don't have any more events to process
if (poll_fd[index].overlapped->InternalHigh <= 0) {
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index eb93635..ff9f397 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -1946,7 +1946,9 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds,
io_result = GetLastError();
}
usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd);
- usbi_free_fd(transfer_priv->pollable_fd.fd);
+ // let handle_callback free the event using the transfer wfd
+ // If you don't use the transfer wfd, you run a risk of trying to free a
+ // newly allocated wfd that took the place of the one from the transfer.
windows_handle_callback(transfer, io_result, io_size);
} else {
usbi_err(ctx, "could not find a matching transfer for fd %x", fds[i]);