Update to 1.0.26

This commit is contained in:
Kate Hsuan 2022-09-30 16:24:59 +08:00
parent b6b18ebcd9
commit 91d4c17a0b
8 changed files with 6 additions and 1367 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/libusb-1.0.24.tar.bz2
/libusb-1.0.25.tar.bz2
/libusb-1.0.26.tar.bz2

View File

@ -1,158 +0,0 @@
From d46cbbac4851ce6e49d8dacb0daa328453eb8a84 Mon Sep 17 00:00:00 2001
From: Benjamin Berg <bberg@redhat.com>
Date: Tue, 22 Feb 2022 11:45:38 +0100
Subject: [PATCH] core: Install first context as implicit default
There was a behaviour change in libusb, which triggers issues when the
API is misused. This caused gutenprint to crash, see
https://bugzilla.redhat.com/show_bug.cgi?id=2055504
For now, work around this by installing an implicit default. But, change
the code to log an error in case this "feature" is being used.
---
libusb/core.c | 16 +++++++++++++---
libusb/libusbi.h | 15 ++++++++++++++-
tests/umockdev.c | 31 +++++++++++++++++++++++++++++++
3 files changed, 58 insertions(+), 4 deletions(-)
diff --git a/libusb/core.c b/libusb/core.c
index 1c1ada1..c75ddae 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -41,6 +41,7 @@ static libusb_log_cb log_handler;
#endif
struct libusb_context *usbi_default_context;
+struct libusb_context *usbi_fallback_context;
static int default_context_refcnt;
static usbi_mutex_static_t default_context_lock = USBI_MUTEX_INITIALIZER;
static struct usbi_option default_context_options[LIBUSB_OPTION_MAX];
@@ -2284,7 +2285,7 @@ int API_EXPORTED libusb_init(libusb_context **ctx)
usbi_mutex_static_lock(&default_context_lock);
- if (!ctx && usbi_default_context) {
+ if (!ctx && default_context_refcnt > 0) {
usbi_dbg(usbi_default_context, "reusing default context");
default_context_refcnt++;
usbi_mutex_static_unlock(&default_context_lock);
@@ -2354,9 +2355,15 @@ int API_EXPORTED libusb_init(libusb_context **ctx)
goto err_io_exit;
}
- if (ctx)
+ if (ctx) {
*ctx = _ctx;
+ if (!usbi_fallback_context) {
+ usbi_fallback_context = _ctx;
+ usbi_warn(usbi_fallback_context, "installing new context as implicit default");
+ }
+ }
+
usbi_mutex_static_unlock(&default_context_lock);
return 0;
@@ -2429,6 +2436,8 @@ void API_EXPORTED libusb_exit(libusb_context *ctx)
if (!ctx)
usbi_default_context = NULL;
+ if (ctx == usbi_fallback_context)
+ usbi_fallback_context = NULL;
usbi_mutex_static_unlock(&default_context_lock);
@@ -2575,7 +2584,8 @@ static void log_v(struct libusb_context *ctx, enum libusb_log_level level,
#else
enum libusb_log_level ctx_level;
- ctx = usbi_get_context(ctx);
+ ctx = ctx ? ctx : usbi_default_context;
+ ctx = ctx ? ctx : usbi_fallback_context;
if (ctx)
ctx_level = ctx->debug;
else
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
index 5f0d5c2..580add8 100644
--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -436,13 +436,26 @@ struct libusb_context {
};
extern struct libusb_context *usbi_default_context;
+extern struct libusb_context *usbi_fallback_context;
extern struct list_head active_contexts_list;
extern usbi_mutex_static_t active_contexts_lock;
static inline struct libusb_context *usbi_get_context(struct libusb_context *ctx)
{
- return ctx ? ctx : usbi_default_context;
+ static int warned = 0;
+
+ if (!ctx) {
+ ctx = usbi_default_context;
+ }
+ if (!ctx) {
+ ctx = usbi_fallback_context;
+ if (ctx && warned == 0) {
+ usbi_err(ctx, "API misuse! Using non-default context as implicit default.");
+ warned = 1;
+ }
+ }
+ return ctx;
}
enum usbi_event_flags {
diff --git a/tests/umockdev.c b/tests/umockdev.c
index b2af512..0e73f94 100644
--- a/tests/umockdev.c
+++ b/tests/umockdev.c
@@ -551,6 +551,32 @@ test_open_close(UMockdevTestbedFixture * fixture, UNUSED_DATA)
libusb_close(handle);
}
+static void
+test_implicit_default(UMockdevTestbedFixture * fixture, UNUSED_DATA)
+{
+ libusb_device **devs = NULL;
+
+ clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
+ g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
+ libusb_free_device_list(devs, TRUE);
+ assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_ERROR, "\\[usbi_get_context\\].*implicit default");
+
+ /* Only warns once */
+ g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
+ libusb_free_device_list(devs, TRUE);
+ clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
+
+ libusb_init(NULL);
+ g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
+ libusb_exit(NULL);
+
+ /* We free late, causing a warning from libusb_exit. However,
+ * we never see this warning (i.e. test success) because it is on a
+ * different context.
+ */
+ libusb_free_device_list(devs, TRUE);
+}
+
static void
test_close_flying(UMockdevTestbedFixture * fixture, UNUSED_DATA)
{
@@ -932,6 +958,11 @@ main(int argc, char **argv)
test_open_close,
test_fixture_teardown);
+ g_test_add("/libusb/implicit-default", UMockdevTestbedFixture, NULL,
+ test_fixture_setup_with_canon,
+ test_implicit_default,
+ test_fixture_teardown);
+
g_test_add("/libusb/close-flying", UMockdevTestbedFixture, NULL,
test_fixture_setup_with_canon,
test_close_flying,
--
2.35.1

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +0,0 @@
From 2529a3fc4f987f93e0774af865ac7cb6557bd0c2 Mon Sep 17 00:00:00 2001
From: Benjamin Berg <bberg@redhat.com>
Date: Fri, 4 Feb 2022 22:50:28 +0100
Subject: [PATCH] core: Unset device ctx if it has been destroyed
Devices can outlive their context in some cases (in particular with
python garbage collection). Guard against this happening by clearing the
ctx pointer so that it is not pointing to uninitialized memory.
---
libusb/core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libusb/core.c b/libusb/core.c
index 7893ac23..1c1ada14 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -2441,6 +2441,7 @@ void API_EXPORTED libusb_exit(libusb_context *ctx)
for_each_device(_ctx, dev) {
usbi_warn(_ctx, "device %d.%d still referenced",
dev->bus_number, dev->device_address);
+ DEVICE_CTX(dev) = NULL;
}
if (!list_empty(&_ctx->open_devs))

View File

@ -1,133 +0,0 @@
From 1cb11c5ba0d1d1266fe4ddd70f29d081f9d16802 Mon Sep 17 00:00:00 2001
From: Benjamin Berg <bberg@redhat.com>
Date: Tue, 15 Feb 2022 11:13:41 +0100
Subject: [PATCH] io: Track device in usbi_transfer
transfer->dev_handle currently has the behaviour that it will be unset
if the device is closed. The sync API uses this fact to catch an error
case.
In other cases, transfer->dev_handle will keep its value, which means
that if the transfer lives longer than the device handle, the pointer
becomes invalid.
The transfer does however keep a reference to the device, which owns the
pointer to the context. As such, we can track this reference internal to
the transfer, and it is set while the transfer is in-flight.
With this, switch the logging infrastructure to use itransfer->dev->ctx
while checking that itransfer->dev is non-NULL.
Note that this was a regression caused by 6cae9c6dbd74 ("core: update
usbi_dbg to take the context as an argument"), specifically when
resolving the context while freeing a transfer after closing a device.
Note that the transfer will now keep a reference to the device until it
is free'ed. This allows it to use the correct context for logging even
in libusb_free_transfer.
The alternative to all this would be to just explicitly pass NULL to the
log handler in libusb_free_transfer.
---
libusb/io.c | 20 ++++++++++++--------
libusb/libusbi.h | 10 +++++++---
2 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/libusb/io.c b/libusb/io.c
index 0d2ac9ea..b919e9d9 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -1344,6 +1344,8 @@ void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer)
itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
usbi_mutex_destroy(&itransfer->lock);
+ if (itransfer->dev)
+ libusb_unref_device(itransfer->dev);
priv_size = PTR_ALIGN(usbi_backend.transfer_priv_size);
ptr = (unsigned char *)itransfer - priv_size;
@@ -1489,9 +1491,15 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
{
struct usbi_transfer *itransfer =
LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
- struct libusb_context *ctx = TRANSFER_CTX(transfer);
+ struct libusb_context *ctx;
int r;
+ assert(transfer->dev_handle);
+ if (itransfer->dev)
+ libusb_unref_device(itransfer->dev);
+ itransfer->dev = libusb_ref_device(transfer->dev_handle->dev);
+
+ ctx = HANDLE_CTX(transfer->dev_handle);
usbi_dbg(ctx, "transfer %p", transfer);
/*
@@ -1551,8 +1559,6 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
r = usbi_backend.submit_transfer(itransfer);
if (r == LIBUSB_SUCCESS) {
itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT;
- /* keep a reference to this device */
- libusb_ref_device(transfer->dev_handle->dev);
}
usbi_mutex_unlock(&itransfer->lock);
@@ -1659,7 +1665,6 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
{
struct libusb_transfer *transfer =
USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct libusb_device_handle *dev_handle = transfer->dev_handle;
struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
uint8_t flags;
int r;
@@ -1693,7 +1698,6 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
* this point. */
if (flags & LIBUSB_TRANSFER_FREE_TRANSFER)
libusb_free_transfer(transfer);
- libusb_unref_device(dev_handle->dev);
return r;
}
@@ -1727,10 +1731,10 @@ int usbi_handle_transfer_cancellation(struct usbi_transfer *itransfer)
* function will be called the next time an event handler runs. */
void usbi_signal_transfer_completion(struct usbi_transfer *itransfer)
{
- libusb_device_handle *dev_handle = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)->dev_handle;
+ struct libusb_device *dev = itransfer->dev;
- if (dev_handle) {
- struct libusb_context *ctx = HANDLE_CTX(dev_handle);
+ if (dev) {
+ struct libusb_context *ctx = DEVICE_CTX(dev);
unsigned int event_flags;
usbi_mutex_lock(&ctx->event_data_lock);
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
index 158a9af5..5f0d5c2e 100644
--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -329,10 +329,11 @@ void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
#endif /* ENABLE_LOGGING */
#define DEVICE_CTX(dev) ((dev)->ctx)
-#define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev))
-#define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle))
+#define HANDLE_CTX(handle) ((handle) ? DEVICE_CTX((handle)->dev) : NULL)
#define ITRANSFER_CTX(itransfer) \
- (TRANSFER_CTX(USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer)))
+ ((itransfer)->dev ? DEVICE_CTX((itransfer)->dev) : NULL)
+#define TRANSFER_CTX(transfer) \
+ (ITRANSFER_CTX(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)))
#define IS_EPIN(ep) (0 != ((ep) & LIBUSB_ENDPOINT_IN))
#define IS_EPOUT(ep) (!IS_EPIN(ep))
@@ -562,6 +563,9 @@ struct usbi_transfer {
uint32_t state_flags; /* Protected by usbi_transfer->lock */
uint32_t timeout_flags; /* Protected by the flying_stransfers_lock */
+ /* This is used for logging mostly. As long as it is set, the */
+ struct libusb_device *dev;
+
/* this lock is held during libusb_submit_transfer() and
* libusb_cancel_transfer() (allowing the OS backend to prevent duplicate
* cancellation, submission-during-cancellation, etc). the OS backend

View File

@ -1,3 +1,6 @@
* Fri Sep 30 2022 Kate Hsuan <hpa@redhat.com> 1.0.26-1
- Update to 1.0.26
* Wed Feb 02 2022 Benjamin Berg <bberg@redhat.com> 1.0.25-1
- Update to 1.0.25

View File

@ -1,6 +1,6 @@
Summary: Library for accessing USB devices
Name: libusb1
Version: 1.0.25
Version: 1.0.26
Release: %autorelease
Source0: https://github.com/libusb/libusb/releases/download/v%{version}/libusb-%{version}.tar.bz2
License: LGPLv2+
@ -13,18 +13,6 @@ BuildRequires: gcc
Provides: libusbx = %{version}-%{release}
Obsoletes: libusbx < %{version}-%{release}
# Fix a crash after libusb_exit API has been misused
# https://bugzilla.redhat.com/show_bug.cgi?id=2050638
Patch0001: https://github.com/libusb/libusb/pull/1058.patch
# Fix a crash if a transfer outlives closing the device
Patch0002: https://github.com/libusb/libusb/pull/1073.patch
# Add umockdev based tests from https://github.com/libusb/libusb/pull/1078
Patch0003: 0001-tests-Add-some-umockdev-based-tests.patch
# Work around API misuse in gutenprint
# https://bugzilla.redhat.com/show_bug.cgi?id=2056326
Patch9999: 0001-core-Install-first-context-as-implicit-default.patch
%description
This package provides a way for applications to access USB devices.

View File

@ -1 +1 @@
SHA512 (libusb-1.0.25.tar.bz2) = f1e6e5577d4bd1ff136927dc66c615014a06ac332ddd797b1d1ad5f7b68e2405e66068dcb210e2f0ae3e31681603ef72efbd88bf7fbe0eb41ce700fdc3f92f9d
SHA512 (libusb-1.0.26.tar.bz2) = fcdb85c98f21639668693c2fd522814d440972d65883984c4ae53d0555bdbdb7e8c7a32199cd4b01113556a1eb5be7841b750cc73c9f6bda79bfe1af80914e71