QTapGestureRecognizer: fix UB (invalid downcast) in recognize()

The old code cast the event to QTouchEvent* ahead of checking that it
actually is of a type() that suggests is-a QTouchEvent.

I'm not sure this was UB, because we weren't dereferencing the result
until after we checked type(). Then again, who am I to argue with
compiler writers (= same people that write ubsan)?

Says UBSan:

  qstandardgestures.cpp:402:29: runtime error: downcast of address 0x7fffedb894f0 which does not point to an object of type 'QTouchEvent'
   0x7fffedb894f0: note: object is of type 'QEvent'
    ff 7f 00 00  c0 db 01 cf 99 7f 00 00  15 00 00 00 01 00 00 00  01 00 00 00 99 7f 00 00  b6 c4 14 f5
                 ^~~~~~~~~~~~~~~~~~~~~~~
                 vptr for 'QEvent'

Fix my delaying the cast until after we know that event is-a
QTouchEvent. All other recognize() overload already behaved correctly.

As a drive-by, use auto (RHS contains the type) and mark the result
const.

Amends the start of the public history.

Pick-to: 6.8 6.5 5.15
Change-Id: Ifa9e940232b93b2ecf666c35536519a8385c9800
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
(cherry picked from commit 03daf6685eda50d79b9b4598ebf6c301def73daa)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2025-03-26 21:40:00 +01:00 committed by Qt Cherry-pick Bot
parent e215b930e2
commit 15b3d364ae

View File

@ -399,12 +399,11 @@ QGestureRecognizer::Result QTapGestureRecognizer::recognize(QGesture *state,
QTapGesture *q = static_cast<QTapGesture *>(state); QTapGesture *q = static_cast<QTapGesture *>(state);
QTapGesturePrivate *d = q->d_func(); QTapGesturePrivate *d = q->d_func();
const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture; QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture;
switch (event->type()) { switch (event->type()) {
case QEvent::TouchBegin: { case QEvent::TouchBegin: {
const auto ev = static_cast<const QTouchEvent *>(event);
d->position = ev->points().at(0).position(); d->position = ev->points().at(0).position();
q->setHotSpot(ev->points().at(0).globalPosition()); q->setHotSpot(ev->points().at(0).globalPosition());
result = QGestureRecognizer::TriggerGesture; result = QGestureRecognizer::TriggerGesture;
@ -412,6 +411,7 @@ QGestureRecognizer::Result QTapGestureRecognizer::recognize(QGesture *state,
} }
case QEvent::TouchUpdate: case QEvent::TouchUpdate:
case QEvent::TouchEnd: { case QEvent::TouchEnd: {
const auto ev = static_cast<const QTouchEvent *>(event);
if (q->state() != Qt::NoGesture && ev->points().size() == 1) { if (q->state() != Qt::NoGesture && ev->points().size() == 1) {
const QEventPoint &p = ev->points().at(0); const QEventPoint &p = ev->points().at(0);
QPoint delta = p.position().toPoint() - p.pressPosition().toPoint(); QPoint delta = p.position().toPoint() - p.pressPosition().toPoint();