Work around API misuse in gutenprint
https://bugzilla.redhat.com/show_bug.cgi?id=2056326
This commit is contained in:
parent
11a16ae2a8
commit
261c00aec2
2 changed files with 179 additions and 0 deletions
175
0001-core-Install-first-context-as-implicit-default.patch
Normal file
175
0001-core-Install-first-context-as-implicit-default.patch
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
From f74f1e21b6201ec803347ddaf2737cdaf9a1180a 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 | 24 ++++++++++++++++--------
|
||||
libusb/libusbi.h | 8 +++++++-
|
||||
tests/umockdev.c | 26 ++++++++++++++++++++++++++
|
||||
3 files changed, 49 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/libusb/core.c b/libusb/core.c
|
||||
index 1c1ada1..c56df72 100644
|
||||
--- a/libusb/core.c
|
||||
+++ b/libusb/core.c
|
||||
@@ -41,7 +41,7 @@ static libusb_log_cb log_handler;
|
||||
#endif
|
||||
|
||||
struct libusb_context *usbi_default_context;
|
||||
-static int default_context_refcnt;
|
||||
+int usbi_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,9 +2284,9 @@ int API_EXPORTED libusb_init(libusb_context **ctx)
|
||||
|
||||
usbi_mutex_static_lock(&default_context_lock);
|
||||
|
||||
- if (!ctx && usbi_default_context) {
|
||||
+ if (!ctx && usbi_default_context_refcnt > 0) {
|
||||
usbi_dbg(usbi_default_context, "reusing default context");
|
||||
- default_context_refcnt++;
|
||||
+ usbi_default_context_refcnt++;
|
||||
usbi_mutex_static_unlock(&default_context_lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -2331,7 +2331,7 @@ int API_EXPORTED libusb_init(libusb_context **ctx)
|
||||
/* default context must be initialized before calling usbi_dbg */
|
||||
if (!ctx) {
|
||||
usbi_default_context = _ctx;
|
||||
- default_context_refcnt = 1;
|
||||
+ usbi_default_context_refcnt = 1;
|
||||
usbi_dbg(usbi_default_context, "created default context");
|
||||
}
|
||||
|
||||
@@ -2357,6 +2357,12 @@ int API_EXPORTED libusb_init(libusb_context **ctx)
|
||||
if (ctx)
|
||||
*ctx = _ctx;
|
||||
|
||||
+ if (usbi_default_context == NULL) {
|
||||
+ usbi_default_context = _ctx;
|
||||
+ usbi_default_context_refcnt = 0;
|
||||
+ usbi_dbg(usbi_default_context, "installing new context as implicit default");
|
||||
+ }
|
||||
+
|
||||
usbi_mutex_static_unlock(&default_context_lock);
|
||||
|
||||
return 0;
|
||||
@@ -2373,7 +2379,7 @@ err_free_ctx:
|
||||
if (!ctx) {
|
||||
/* clear default context that was not fully initialized */
|
||||
usbi_default_context = NULL;
|
||||
- default_context_refcnt = 0;
|
||||
+ usbi_default_context_refcnt = 0;
|
||||
}
|
||||
|
||||
usbi_mutex_destroy(&_ctx->open_devs_lock);
|
||||
@@ -2407,7 +2413,7 @@ void API_EXPORTED libusb_exit(libusb_context *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
- if (--default_context_refcnt > 0) {
|
||||
+ if (--usbi_default_context_refcnt > 0) {
|
||||
usbi_dbg(ctx, "not destroying default context");
|
||||
usbi_mutex_static_unlock(&default_context_lock);
|
||||
return;
|
||||
@@ -2427,8 +2433,10 @@ void API_EXPORTED libusb_exit(libusb_context *ctx)
|
||||
if (usbi_backend.exit)
|
||||
usbi_backend.exit(_ctx);
|
||||
|
||||
- if (!ctx)
|
||||
+ if (!ctx || ctx == usbi_default_context) {
|
||||
usbi_default_context = NULL;
|
||||
+ assert(usbi_default_context_refcnt == 0);
|
||||
+ }
|
||||
|
||||
usbi_mutex_static_unlock(&default_context_lock);
|
||||
|
||||
@@ -2575,7 +2583,7 @@ 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;
|
||||
if (ctx)
|
||||
ctx_level = ctx->debug;
|
||||
else
|
||||
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
|
||||
index 5f0d5c2..a404cff 100644
|
||||
--- a/libusb/libusbi.h
|
||||
+++ b/libusb/libusbi.h
|
||||
@@ -436,13 +436,19 @@ struct libusb_context {
|
||||
};
|
||||
|
||||
extern struct libusb_context *usbi_default_context;
|
||||
+extern int usbi_default_context_refcnt;
|
||||
|
||||
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;
|
||||
+ if (!ctx && usbi_default_context) {
|
||||
+ if (usbi_default_context_refcnt == 0)
|
||||
+ usbi_err(usbi_default_context, "API misuse! Using non-default context as implicit default.");
|
||||
+ ctx = usbi_default_context;
|
||||
+ }
|
||||
+ return ctx;
|
||||
}
|
||||
|
||||
enum usbi_event_flags {
|
||||
diff --git a/tests/umockdev.c b/tests/umockdev.c
|
||||
index b2af512..7de0aae 100644
|
||||
--- a/tests/umockdev.c
|
||||
+++ b/tests/umockdev.c
|
||||
@@ -551,6 +551,27 @@ 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");
|
||||
+
|
||||
+ 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 +953,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
|
||||
|
||||
|
|
@ -21,6 +21,10 @@ 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.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue