diff options
author | Paul Olav Tvete <paul.tvete@qt.io> | 2020-12-23 13:18:04 +0100 |
---|---|---|
committer | Paul Olav Tvete <paul.tvete@qt.io> | 2020-12-23 15:25:02 +0100 |
commit | c80d6473fbeb43074fb63db66e162e76cb2bf3ef (patch) | |
tree | 23703fe65d69a19fc05c3c6209cafad654929f2c /src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | |
parent | 3729d37dd9ad38044242097adaa4bd74e2d5de87 (diff) |
Fix out-of-bounds write
Change ac210c73e4 introduced the requirement that all input devices with
Scroll capability must have a QXcbScrollingDevicePrivate as their d_ptr.
However, this was not enforced, and would fail for the "Virtual core
pointer".
To fix this, always use qobject_cast to verify that the device is of the
correct type.
Change-Id: I4a6b1d4d79308eb04e9f52dda00294fffe377bdf
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbconnection_xi2.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 03c45dfc3e..04d2c57e9e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -433,7 +433,7 @@ void QXcbConnection::xi2SetupSlavePointerDevice(void *info, bool removeExisting, scrollingDeviceP->buttonCount = buttonCount; if (master) scrollingDeviceP->seatName = master->seatName(); - QWindowSystemInterface::registerInputDevice(new QXcbScrollingMouse(*scrollingDeviceP, master)); + QWindowSystemInterface::registerInputDevice(new QXcbScrollingDevice(*scrollingDeviceP, master)); } else { QWindowSystemInterface::registerInputDevice(new QPointingDevice( name, deviceInfo->deviceid, @@ -991,8 +991,13 @@ void QXcbConnection::xi2HandleDeviceChangedEvent(void *event) } } -void QXcbConnection::xi2UpdateScrollingDevice(QXcbScrollingDevicePrivate *scrollingDevice) +void QXcbConnection::xi2UpdateScrollingDevice(QInputDevice *dev) { + QXcbScrollingDevice *scrollDev = qobject_cast<QXcbScrollingDevice *>(dev); + if (!scrollDev || !scrollDev->capabilities().testFlag(QInputDevice::Capability::Scroll)) + return; + QXcbScrollingDevicePrivate *scrollingDevice = QXcbScrollingDevice::get(scrollDev); + auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, xcb_connection(), scrollingDevice->systemId); if (!reply || reply->num_infos <= 0) { qCDebug(lcQpaXInputDevices, "scrolling device %lld no longer present", scrollingDevice->systemId); @@ -1026,30 +1031,27 @@ void QXcbConnection::xi2UpdateScrollingDevices() { const auto &devices = QInputDevice::devices(); for (const QInputDevice *dev : devices) { - if (dev->capabilities().testFlag(QInputDevice::Capability::Scroll)) { - const auto devPriv = QPointingDevicePrivate::get(static_cast<QPointingDevice *>(const_cast<QInputDevice *>(dev))); - xi2UpdateScrollingDevice(static_cast<QXcbScrollingDevicePrivate *>(devPriv)); - } + if (dev->capabilities().testFlag(QInputDevice::Capability::Scroll)) + xi2UpdateScrollingDevice(const_cast<QInputDevice *>(dev)); } } -QXcbScrollingDevicePrivate *QXcbConnection::scrollingDeviceForId(int id) +QXcbScrollingDevice *QXcbConnection::scrollingDeviceForId(int id) { const QPointingDevice *dev = QPointingDevicePrivate::pointingDeviceById(id); - if (!dev) + if (!dev|| !dev->capabilities().testFlag(QInputDevice::Capability::Scroll)) return nullptr; - if (!dev->capabilities().testFlag(QInputDevice::Capability::Scroll)) - return nullptr; - auto devPriv = QPointingDevicePrivate::get(const_cast<QPointingDevice *>(dev)); - return static_cast<QXcbScrollingDevicePrivate *>(devPriv); + return qobject_cast<QXcbScrollingDevice *>(const_cast<QPointingDevice *>(dev)); } void QXcbConnection::xi2HandleScrollEvent(void *event, const QPointingDevice *dev) { auto *xiDeviceEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event); - if (!dev->capabilities().testFlag(QInputDevice::Capability::Scroll)) + + const QXcbScrollingDevice *scrollDev = qobject_cast<const QXcbScrollingDevice *>(dev); + if (!scrollDev || !scrollDev->capabilities().testFlag(QInputDevice::Capability::Scroll)) return; - const auto scrollingDevice = static_cast<const QXcbScrollingDevicePrivate *>(QPointingDevicePrivate::get(dev)); + const QXcbScrollingDevicePrivate *scrollingDevice = QXcbScrollingDevice::get(scrollDev); if (xiDeviceEvent->event_type == XCB_INPUT_MOTION && scrollingDevice->orientations) { if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) { |