[Spice-devel] [PATCH] Avoid passing libusb functions as callbacks

jorge.olmos at flexvdi.com jorge.olmos at flexvdi.com
Fri Aug 17 13:12:35 UTC 2018


From: Jorge Olmos <jorge.olmos at flexvdi.com>

When building spice-gtk for windows:
- libusb uses __stdcall calling convention when compiled for win32. It does
not include an option to be compiled with __cdecl calling convention.
Directly calling libusb functions works fine. But it is a problem when its
functions are passed as callbacks to a function that expects other calling
convention.
- glib uses __cdecl calling convention and expects the functions it
receives as parameters to follow __cdecl convention.

So the lines included in spice-gtk like:
     g_clear_pointer(&priv->device, libusb_unref_device);
cause libusb_unref_device (compiled with _stdcall convention) to be called
with __cdecl convention. This causes stack corruption, and hence crashes.
---
 src/channel-usbredir.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/channel-usbredir.c b/src/channel-usbredir.c
index 6ffe546..1d9c380 100644
--- a/src/channel-usbredir.c
+++ b/src/channel-usbredir.c
@@ -352,7 +352,8 @@ static void spice_usbredir_channel_open_acl_cb(
         spice_usbredir_channel_open_device(channel, &err);
     }
     if (err) {
-        g_clear_pointer(&priv->device, libusb_unref_device);
+        libusb_unref_device(priv->device);
+        priv->device = NULL;
         g_boxed_free(spice_usb_device_get_type(), priv->spice_device);
         priv->spice_device = NULL;
         priv->state  = STATE_DISCONNECTED;
@@ -383,7 +384,8 @@ _open_device_async_cb(GTask *task,
     spice_usbredir_channel_lock(channel);
 
     if (!spice_usbredir_channel_open_device(channel, &err)) {
-        g_clear_pointer(&priv->device, libusb_unref_device);
+        libusb_unref_device(priv->device);
+        priv->device = NULL;
         g_boxed_free(spice_usb_device_get_type(), priv->spice_device);
         priv->spice_device = NULL;
     }
@@ -504,7 +506,8 @@ void spice_usbredir_channel_disconnect_device(SpiceUsbredirChannel *channel)
 
         /* This also closes the libusb handle we passed from open_device */
         usbredirhost_set_device(priv->host, NULL);
-        g_clear_pointer(&priv->device, libusb_unref_device);
+        libusb_unref_device(priv->device);
+        priv->device = NULL;
         g_boxed_free(spice_usb_device_get_type(), priv->spice_device);
         priv->spice_device = NULL;
         priv->state  = STATE_DISCONNECTED;
-- 
2.14.4



More information about the Spice-devel mailing list