summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2022-09-09 13:14:23 +0100
committerRichard Hughes <richard@hughsie.com>2022-09-10 09:21:19 +0100
commit0f605ed23f2f9ea5c2ac28cc772f1e781ffa08ba (patch)
treeb857d93963964f9705d55d164556babfb1f76cea
parentd6f16fb540194ece1945e6beed6eafc4dac15336 (diff)
downloadgusb-0f605ed23f2f9ea5c2ac28cc772f1e781ffa08ba.tar.gz
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.
-rw-r--r--gusb/gusb-device.c51
1 files 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;