From 0f605ed23f2f9ea5c2ac28cc772f1e781ffa08ba Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Fri, 9 Sep 2022 13:14:23 +0100 Subject: Do not copy event data when not-required This will prevent crashes if the caller is casting from a const buffer to a mutable buffer. --- gusb/gusb-device.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/gusb/gusb-device.c b/gusb/gusb-device.c index ebba9a9..0458451 100644 --- a/gusb/gusb-device.c +++ b/gusb/gusb-device.c @@ -1883,6 +1883,30 @@ g_usb_device_control_transfer_cb(struct libusb_transfer *transfer) g_object_unref(task); } +static gboolean +gusb_memcpy_bytes_safe(guint8 *dst, gsize dstsz, GBytes *bytes, GError **error) +{ + /* sanity check */ + if (dstsz < g_bytes_get_size(bytes)) { + g_set_error( + error, + G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + "cannot copy source buffer of size 0x%x into destination buffer of size 0x%x", + (guint)g_bytes_get_size(bytes), + (guint)dstsz); + return FALSE; + } + + /* data is the same */ + if (memcmp(dst, g_bytes_get_data(bytes, NULL), dstsz) == 0) + return TRUE; + + /* if this explodes it's because the caller has cast an immutable buffer to a guint8* */ + memcpy(dst, g_bytes_get_data(bytes, NULL), dstsz); + return TRUE; +} + /** * g_usb_device_control_transfer_async: * @self: a #GUsbDevice @@ -1976,8 +2000,15 @@ g_usb_device_control_transfer_async(GUsbDevice *self, event_id); return; } + if (!gusb_memcpy_bytes_safe(data, length, bytes, &error)) { + g_task_report_error(self, + callback, + user_data, + g_usb_device_control_transfer_async, + error); + return; + } task = g_task_new(self, cancellable, callback, user_data); - memcpy(data, g_bytes_get_data(bytes, NULL), g_bytes_get_size(bytes)); g_task_return_int(task, g_bytes_get_size(bytes)); g_object_unref(task); return; @@ -2146,8 +2177,15 @@ g_usb_device_bulk_transfer_async(GUsbDevice *self, event_id); return; } + if (!gusb_memcpy_bytes_safe(data, length, bytes, &error)) { + g_task_report_error(self, + callback, + user_data, + g_usb_device_control_transfer_async, + error); + return; + } task = g_task_new(self, cancellable, callback, user_data); - memcpy(data, g_bytes_get_data(bytes, NULL), g_bytes_get_size(bytes)); g_task_return_int(task, g_bytes_get_size(bytes)); g_object_unref(task); return; @@ -2305,8 +2343,15 @@ g_usb_device_interrupt_transfer_async(GUsbDevice *self, event_id); return; } + if (!gusb_memcpy_bytes_safe(data, length, bytes, &error)) { + g_task_report_error(self, + callback, + user_data, + g_usb_device_control_transfer_async, + error); + return; + } task = g_task_new(self, cancellable, callback, user_data); - memcpy(data, g_bytes_get_data(bytes, NULL), g_bytes_get_size(bytes)); g_task_return_int(task, g_bytes_get_size(bytes)); g_object_unref(task); return; -- cgit v1.2.1