core: Install first context as implicit default (and warn about its use)

There was a behaviour change in libusb 1.0.25 which triggers issues when
the API is misused. This caused for instance gutenprint to crash, see
https://bugzilla.redhat.com/show_bug.cgi?id=2055504

This seems to affect several applications "out in the wild".

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.

This will allow some grace time for developers to fix their
applications, before we at a later point revert to the stricter
behaviour.

Fixes #1089
diff --git a/libusb/core.c b/libusb/core.c
index 3559470..ec429b7 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -41,6 +41,7 @@
 #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 @@
 
 	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);
@@ -2355,9 +2356,15 @@
 	/* Initialize hotplug after the initial enumeration is done. */
 	usbi_hotplug_init(_ctx);
 
-	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;
@@ -2430,6 +2437,8 @@
 
 	if (!ctx)
 		usbi_default_context = NULL;
+	if (ctx == usbi_fallback_context)
+		usbi_fallback_context = NULL;
 
 	usbi_mutex_static_unlock(&default_context_lock);
 
@@ -2576,7 +2585,8 @@
 #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 7618236..b1fc88c 100644
--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -436,13 +436,26 @@
 };
 
 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/libusb/version_nano.h b/libusb/version_nano.h
index 4271170..26ed7e7 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11711
+#define LIBUSB_NANO 11712
diff --git a/tests/umockdev.c b/tests/umockdev.c
index 1eda532..488edc2 100644
--- a/tests/umockdev.c
+++ b/tests/umockdev.c
@@ -559,6 +559,32 @@
 }
 
 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)
 {
 	UsbChat chat[] = {
@@ -1101,6 +1127,11 @@
 	           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,