QWidgetWindow: fix UB (invalid downcast) in Private::handleDragEnterEvent()
The handleDragEnterEvent() function is not only called for QEvent::DragEnter, but also, in handleDragMoveEvent(), for QEvent::DragMove, in which case the fully-derived event passed as an argument is a QDragMoveEvent, and not its subclass QDragEnterEvent. Code in Qt seems to assume that it's ok to cast an object down to a more-derived class than the most-derived dynamic type, as long as no extra state is being added between the two, but C++ does not chare that view. Says UBSan: qwidgetwindow.cpp:1000:38: runtime error: downcast of address 0x7ffe7b34c6e0 which does not point to an object of type 'QDragEnterEvent' 0x7ffe7b34c6e0: note: object is of type 'QDragMoveEvent' 00 00 00 00 e0 62 70 42 aa 7f 00 00 3d 00 00 00 00 00 00 00 00 00 00 00 00 c0 58 40 00 00 00 00 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QDragMoveEvent' Furtunately, handleDragEnterEvent() doesn't actually need its argument to be a QDragEnterEvent; QDragMoveEvent suffices, so we can just change the argument type back to QDragMoveEvent and remove the cast in handleDragMoveEvent(). Add a bit of \internal docs to describe the discrepancy between the function's name and argument type. Amends f8944a7f07112c85dc4f66848cabb490514cd28e. Picking all the way, because this is risk-less: Either the code compiles and then it works as before (minus the UB), or it doesn't compile. Pick-to: 6.8 6.5 5.15 Change-Id: I5be53b023d389902b43e9a896d074edea1c4ff2d Reviewed-by: Axel Spoerl <axel.spoerl@qt.io> (cherry picked from commit e89c0a7fb54a15b8df1d2938e2f01ef14f3bf7e5) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
db63625c50
commit
54e67a13aa
@ -948,7 +948,17 @@ static QWidget *findDnDTarget(QWidget *parent, const QPoint &pos)
|
|||||||
return widget;
|
return widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWidgetWindow::handleDragEnterEvent(QDragEnterEvent *event, QWidget *widget)
|
/*!
|
||||||
|
\internal
|
||||||
|
|
||||||
|
Sends \a event to \a widget.
|
||||||
|
|
||||||
|
Also called from dragMoveEvent(), in which case \a event is-a
|
||||||
|
QDragMoveEvent only, not a full QDragEnterEvent, which is why this function
|
||||||
|
takes \a event as a QDragMoveEvent and not, as one would expect,
|
||||||
|
QDragEnterEvent (downcast would be UB).
|
||||||
|
*/
|
||||||
|
void QWidgetWindow::handleDragEnterEvent(QDragMoveEvent *event, QWidget *widget)
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_dragTarget == nullptr);
|
Q_ASSERT(m_dragTarget == nullptr);
|
||||||
if (!widget)
|
if (!widget)
|
||||||
@ -997,7 +1007,7 @@ void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event)
|
|||||||
// widget might have been deleted when handling the leaveEvent
|
// widget might have been deleted when handling the leaveEvent
|
||||||
if (widget) {
|
if (widget) {
|
||||||
// Send DragEnter to new widget.
|
// Send DragEnter to new widget.
|
||||||
handleDragEnterEvent(static_cast<QDragEnterEvent*>(event), widget);
|
handleDragEnterEvent(event, widget);
|
||||||
// Handling 'DragEnter' should suffice for the application.
|
// Handling 'DragEnter' should suffice for the application.
|
||||||
translated.setDropAction(event->dropAction());
|
translated.setDropAction(event->dropAction());
|
||||||
translated.setAccepted(event->isAccepted());
|
translated.setAccepted(event->isAccepted());
|
||||||
|
@ -65,7 +65,7 @@ protected:
|
|||||||
void handleWheelEvent(QWheelEvent *);
|
void handleWheelEvent(QWheelEvent *);
|
||||||
#endif
|
#endif
|
||||||
#if QT_CONFIG(draganddrop)
|
#if QT_CONFIG(draganddrop)
|
||||||
void handleDragEnterEvent(QDragEnterEvent *, QWidget *widget = nullptr);
|
void handleDragEnterEvent(QDragMoveEvent *, QWidget *widget = nullptr);
|
||||||
void handleDragMoveEvent(QDragMoveEvent *);
|
void handleDragMoveEvent(QDragMoveEvent *);
|
||||||
void handleDragLeaveEvent(QDragLeaveEvent *);
|
void handleDragLeaveEvent(QDragLeaveEvent *);
|
||||||
void handleDropEvent(QDropEvent *);
|
void handleDropEvent(QDropEvent *);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user