Skip to content

Fix for platform socklen_t on other C libraries than glibc.#6

Closed
dflogeras wants to merge 1 commit intoqt:devfrom
dflogeras:fix-socklen_t-musl-uclibc
Closed

Fix for platform socklen_t on other C libraries than glibc.#6
dflogeras wants to merge 1 commit intoqt:devfrom
dflogeras:fix-socklen_t-musl-uclibc

Conversation

@dflogeras
Copy link
Contributor

Would be awesome to get this merged for 5.5.1.

…found here http://patchwork.openembedded.org/patch/94947/ and tested with armv6j-hardfloat-linux-uclibc and armv6j-hardfloat-linux-musl.
@ossilator
Copy link
Contributor

@ossilator ossilator closed this Sep 29, 2015
qtprojectorg pushed a commit that referenced this pull request Jul 31, 2016
Before actually deleting QTreeWidgetItems from QTree{Model,Widget{,Item}} dtors,
their 'view' members need to be set to nullptr, lest they attempt to delist
themselves from the list of top-level items.

For the QTreeModel::headerItem, this was forgottten.

Found by UBSan:

  qtreewidget.cpp:1488:70: runtime error: member call on address 0x7ffd843dd470 which does not point to an object of type 'QAbstractItemView'
  0x7ffd843dd470: note: object is of type 'QWidget'
    #0 0x2b83d5b48323 in QTreeWidgetItem::~QTreeWidgetItem() src/widgets/itemviews/qtreewidget.cpp:1488
    #1 0x2b83d5b48860 in QTreeWidgetItem::~QTreeWidgetItem() src/widgets/itemviews/qtreewidget.cpp:1535
    #2 0x2b83d5b41659 in QTreeModel::~QTreeModel() src/widgets/itemviews/qtreewidget.cpp:143
    #3 0x2b83d5b41bc0 in QTreeModel::~QTreeModel() src/widgets/itemviews/qtreewidget.cpp:146
    #4 0x2b83df220747 in QObjectPrivate::deleteChildren() src/corelib/kernel/qobject.cpp:2010
    #5 0x2b83d4603dd0 in QWidget::~QWidget() src/widgets/kernel/qwidget.cpp:1675
    #6 0x2b83d4d76066 in QFrame::~QFrame() src/widgets/widgets/qframe.cpp:256
    #7 0x2b83d5270442 in QAbstractScrollArea::~QAbstractScrollArea() src/widgets/widgets/qabstractscrollarea.cpp:575
    #8 0x2b83d5733eb9 in QAbstractItemView::~QAbstractItemView() src/widgets/itemviews/qabstractitemview.cpp:617
    #9 0x2b83d598b216 in QTreeView::~QTreeView() src/widgets/itemviews/qtreeview.cpp:206
    #10 0x2b83d5b218b6 in QTreeWidget::~QTreeWidget() src/widgets/itemviews/qtreewidget.cpp:2549
    #11 0x4eef42 in tst_QTreeWidgetItemIterator::updateIfModifiedFromWidget() tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp:1089

Change-Id: I57c277adee8c99eb07b274d6d8ea1f6fbf3575be
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
qtprojectorg pushed a commit that referenced this pull request Sep 22, 2016
…in Private::canBeNativeDialog()

Found by UBSan:

  qfontdialog_p.h:77:5: runtime error: downcast of address 0x7ffc3ceadc90 which does not point to an object of type 'QFontDialog'
  0x7ffc3ceadc90: note: object is of type 'QDialog'
   fc 7f 00 00  38 5f a8 27 fc 2a 00 00  60 e2 14 02 00 00 00 00  10 61 a8 27 fc 2a 00 00  00 00 00 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QDialog'
    #0 0x2afc24d29490 in QFontDialogPrivate::q_func() const qfontdialog_p.h:77
    #1 0x2afc24d29490 in QFontDialogPrivate::canBeNativeDialog() const qfontdialog.cpp:1033
    #2 0x2afc24c93f56 in QDialog::setVisible(bool) qdialog.cpp:696
    #3 0x2afc24c7b27a in QDialog::~QDialog() qdialog.cpp:357
    #4 0x2afc24d286a6 in QFontDialog::~QFontDialog() qfontdialog.cpp:339
    #5 0x2afc24d481a2 in QFontDialogPrivate::getFont(bool*, QFont const&, QWidget*, QString const&, QFlags<QFontDialog::FontDialogOption>) qfontdialog.cpp:402
    #6 0x2afc24d483f1 in QFontDialog::getFont(bool*, QWidget*) qfontdialog.cpp:396
    #7 0x407652 in tst_QFontDialog::testGetFont() tst_qfontdialog.cpp:120

  qcolordialog.cpp:86:5: runtime error: downcast of address 0x7ffdf50c1ec0 which does not point to an object of type 'QColorDialog'
  0x7ffdf50c1ec0: note: object is of type 'QDialog'
   fd 7f 00 00  d8 6e c7 23 b7 2a 00 00  50 c1 af 01 00 00 00 00  b0 70 c7 23 b7 2a 00 00  00 00 1a 1e
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QDialog'
    #0 0x2ab720e4ec97 in QColorDialogPrivate::q_func() const qcolordialog.cpp:86
    #1 0x2ab720e4ec97 in QColorDialogPrivate::canBeNativeDialog() const qcolordialog.cpp:1865
    #2 0x2ab720e84ed6 in QDialog::setVisible(bool) qdialog.cpp:696
    #3 0x2ab720e6c1fa in QDialog::~QDialog() qdialog.cpp:357
    #4 0x2ab720e2b276 in QColorDialog::~QColorDialog() qcolordialog.cpp:2187
    #5 0x2ab720e5e2c6 in QColorDialog::getColor(QColor const&, QWidget*, QString const&, QFlags<QColorDialog::ColorDialogOption>) qcolordialog.cpp:2148
    #6 0x2ab720e5e473 in QColorDialog::getRgba(unsigned int, bool*, QWidget*) qcolordialog.cpp:2176
    #7 0x407180 in tst_QColorDialog::testGetRgba() tst_qcolordialog.cpp:118

  qfiledialog_p.h:112:5: runtime error: downcast of address 0x7ffd6858cc60 which does not point to an object of type 'QFileDialog'
  0x7ffd6858cc60: note: object is of type 'QDialog'
   a1 2b 00 00  d8 1e 5e 0c a1 2b 00 00  b0 af 01 20 a1 2b 00 00  b0 20 5e 0c a1 2b 00 00  00 00 46 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QDialog'
    #0 0x2ba10980a9e7 in QFileDialogPrivate::q_func() const qfiledialog_p.h:112
    #1 0x2ba10980a9e7 in QFileDialogPrivate::canBeNativeDialog() const qfiledialog.cpp:695
    #2 0x2ba1097efe36 in QDialog::setVisible(bool) qdialog.cpp:696
    #3 0x2ba1097d715a in QDialog::~QDialog() qdialog.cpp:357
    #4 0x2ba109854c4b in QFileDialog::~QFileDialog() qfiledialog.cpp:380
    #5 0x4179dc in tst_QFiledialog::init() tst_qfiledialog.cpp:175

Fix by replacing Q_Q with the the equivalent expression for QDialog.

We can't re-use QDialogPrivate::q_func() here, since that is private,
and probably should stay like that.

Also fix an invalid member call in
QColorDialogPrivate::canBeNativeDialog():

  qcolordialog.cpp:2050:5: runtime error: member call on address 0x7ffdf50c1ec0 which does not point to an object of type 'QColorDialog'
  0x7ffdf50c1ec0: note: object is of type 'QDialog'
   fd 7f 00 00  d8 6e c7 23 b7 2a 00 00  50 c1 af 01 00 00 00 00  b0 70 c7 23 b7 2a 00 00  00 00 1a 1e
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QDialog'
    #0 0x2ab720e4e5ea in QColorDialog::options() const qcolordialog.cpp:2050
    #1 0x2ab720e4e8c8 in QColorDialogPrivate::canBeNativeDialog() const qcolordialog.cpp:1870
    #2 0x2ab720e84ed6 in QDialog::setVisible(bool) qdialog.cpp:696
    #3 0x2ab720e6c1fa in QDialog::~QDialog() qdialog.cpp:357
    #4 0x2ab720e2b276 in QColorDialog::~QColorDialog() qcolordialog.cpp:2187
    #5 0x2ab720e5e2c6 in QColorDialog::getColor(QColor const&, QWidget*, QString const&, QFlags<QColorDialog::ColorDialogOption>) qcolordialog.cpp:2148
    #6 0x2ab720e5e473 in QColorDialog::getRgba(unsigned int, bool*, QWidget*) qcolordialog.cpp:2176
    #7 0x407180 in tst_QColorDialog::testGetRgba() tst_qcolordialog.cpp:118

by accessing the data member directly instead of through the Public API.

Fix the same code in QFileDialog, even though the autotest coverage is
too limited for UBSan to point that one out explicitly.

Change-Id: Idd278744961435e417d91fb2f89b6d91a94e0c71
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
qtprojectorg pushed a commit that referenced this pull request Sep 22, 2016
The variable 'item' may or may not contain a QGraphicsObject
pointer. Using static_cast on an 'item' that isn't, is UB.

Found by UBSan (which failed to print a message, but the
function names gave it away):

  [...]
  #6  <signal handler called>
  #7  0x00002b18813bec05 in __ubsan::checkDynamicType(void*, void*, unsigned long) () from /opt/gcc/trunk/lib64/libubsan.so.0
  #8  0x00002b18813be0c3 in HandleDynamicTypeCacheMiss(__ubsan::DynamicTypeCacheMissData*, unsigned long, unsigned long, __ubsan::ReportOptions) () from /opt/gcc/trunk/lib64/libubsan.so.0
  #9  0x00002b18813be783 in __ubsan_handle_dynamic_type_cache_miss () from /opt/gcc/trunk/lib64/libubsan.so.0
  #10 0x00002b1875e71d4d in QGraphicsScenePrivate::removeItemHelper(QGraphicsItem*) () at /home/marc/Qt/qt5/qtbase/src/widgets/graphicsview/qgraphicsscene.cpp:720
  #11 0x00002b1875e731ef in QGraphicsScene::removeItem(QGraphicsItem*) () at /home/marc/Qt/qt5/qtbase/src/widgets/graphicsview/qgraphicsscene.cpp:2929
  #12 0x00002b1875e6d05f in QGraphicsScenePrivate::removeItemHelper(QGraphicsItem*) () at /home/marc/Qt/qt5/qtbase/src/widgets/graphicsview/qgraphicsscene.cpp:604
  #13 0x00002b1875e731ef in QGraphicsScene::removeItem(QGraphicsItem*) () at /home/marc/Qt/qt5/qtbase/src/widgets/graphicsview/qgraphicsscene.cpp:2929
  #14 0x00002b1875e73e68 in QGraphicsScene::addItem(QGraphicsItem*) () at /home/marc/Qt/qt5/qtbase/src/widgets/graphicsview/qgraphicsscene.cpp:2505
  #15 0x000000000043d34d in tst_QGraphicsWidget::fontPropagationSceneChange() () at /home/marc/Qt/qt5/qtbase/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp:941
  [...]

Fix by using QGraphicsItem::toGraphicsObject().
Yes, it's that simple...

Change-Id: If04d1b62603cfd808cc7b64946da536c221a0c11
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
qtprojectorg pushed a commit that referenced this pull request Sep 22, 2016
Found by UBSan:

  qgraphicsscene.cpp:1000:40: runtime error: downcast of address 0x2af0d4072b00 which does not point to an object of type 'QGraphicsWidget'
  0x2af0d4072b00: note: object is of type 'QGraphicsObject'
   00 00 00 00  30 f5 26 bd f0 2a 00 00  90 e1 05 d4 f0 2a 00 00  a8 e3 26 bd f0 2a 00 00  d0 33 0f d4
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QGraphicsObject'
    #0 0x2af0badf1305 in QGraphicsScenePrivate::ungrabMouse(QGraphicsItem*, bool) qgraphicsscene.cpp:1000
    #1 0x2af0bae0fc24 in QGraphicsScenePrivate::removeItemHelper(QGraphicsItem*) qgraphicsscene.cpp:692
    #2 0x2af0bacd21f6 in QGraphicsItem::~QGraphicsItem() qgraphicsitem.cpp:1555
    #3 0x2af0bacd4c48 in QGraphicsObject::~QGraphicsObject() qgraphicsitem.cpp:7766
    #4 0x2af0baf7e99c in QGraphicsWidget::~QGraphicsWidget() qgraphicswidget.cpp:231
    #5 0x2af0baf7f8c0 in QGraphicsWidget::~QGraphicsWidget() qgraphicswidget.cpp:282
    #6 0x2af0badcee34 in QGraphicsScene::clear() qgraphicsscene.cpp:2388
    #7 0x2af0badcf3fc in QGraphicsScene::~QGraphicsScene() qgraphicsscene.cpp:1682
    #8 0x4b26f0 in tst_QGraphicsWidget::popupMouseGrabber() tst_qgraphicswidget.cpp:47

Fix by using the existing graphics widget pointer,
determined a line above to be equivalent to 'item',
for the removePopup() function call instead of
casting 'item' itself.

The rest of removePopup() appears to be well-behaved
and doesn't trigger any more UBSan errors, so it was
indeed just the cast which was undefined, no member
calls.

Change-Id: Ia54da90262a7a02f527914a90b0208be0ffc0f0b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
qtprojectorg pushed a commit that referenced this pull request Sep 24, 2016
Found by UBSan, which was so shocked that it crashed:

  #6  <signal handler called>
  #7  __dynamic_cast () at ../../../../gcc/libstdc++-v3/libsupc++/dyncast.cc:50
  #8  0x00002b9278fa1c3b in __ubsan::checkDynamicType(void*, void*, unsigned long) () from /opt/gcc/trunk/lib64/libubsan.so.0
  #9  0x00002b9278fa10c3 in HandleDynamicTypeCacheMiss(__ubsan::DynamicTypeCacheMissData*, unsigned long, unsigned long, __ubsan::ReportOptions) () from /opt/gcc/trunk/lib64/libubsan.so.0
  #10 0x00002b9278fa1783 in __ubsan_handle_dynamic_type_cache_miss () from /opt/gcc/trunk/lib64/libubsan.so.0
  #11 0x00002b926c08ab8d in QApplication::notify(QObject*, QEvent*) () at /home/marc/Qt/qt5/qtbase/src/widgets/kernel/qapplication.cpp:3120

(full backtrace originates in tst_QWidget::testDeletionInEventHandlers(),
testing key events).

Fix is simple: just perform the cast before delivering the event.

Change-Id: Ic26e36f47ef57e980c0dba00900927ff39fe6392
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
qtprojectorg pushed a commit that referenced this pull request Sep 24, 2016
…ivate::canBeNativeDialog()

Found by UBSan:

  qcolordialog.cpp:86:5: runtime error: downcast of address 0x7ffdf50c1ec0 which does not point to an object of type 'QColorDialog'
  0x7ffdf50c1ec0: note: object is of type 'QDialog'
   fd 7f 00 00  d8 6e c7 23 b7 2a 00 00  50 c1 af 01 00 00 00 00  b0 70 c7 23 b7 2a 00 00  00 00 1a 1e
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QDialog'
    #0 0x2ab720e4ec97 in QColorDialogPrivate::q_func() const qcolordialog.cpp:86
    #1 0x2ab720e4ec97 in QColorDialogPrivate::canBeNativeDialog() const qcolordialog.cpp:1865
    #2 0x2ab720e84ed6 in QDialog::setVisible(bool) qdialog.cpp:696
    #3 0x2ab720e6c1fa in QDialog::~QDialog() qdialog.cpp:357
    #4 0x2ab720e2b276 in QColorDialog::~QColorDialog() qcolordialog.cpp:2187
    #5 0x2ab720e5e2c6 in QColorDialog::getColor(QColor const&, QWidget*, QString const&, QFlags<QColorDialog::ColorDialogOption>) qcolordialog.cpp:2148
    #6 0x2ab720e5e473 in QColorDialog::getRgba(unsigned int, bool*, QWidget*) qcolordialog.cpp:2176
    #7 0x407180 in tst_QColorDialog::testGetRgba() tst_qcolordialog.cpp:118

  qfiledialog_p.h:112:5: runtime error: downcast of address 0x7ffd6858cc60 which does not point to an object of type 'QFileDialog'
  0x7ffd6858cc60: note: object is of type 'QDialog'
   a1 2b 00 00  d8 1e 5e 0c a1 2b 00 00  b0 af 01 20 a1 2b 00 00  b0 20 5e 0c a1 2b 00 00  00 00 46 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QDialog'
    #0 0x2ba10980a9e7 in QFileDialogPrivate::q_func() const qfiledialog_p.h:112
    #1 0x2ba10980a9e7 in QFileDialogPrivate::canBeNativeDialog() const qfiledialog.cpp:695
    #2 0x2ba1097efe36 in QDialog::setVisible(bool) qdialog.cpp:696
    #3 0x2ba1097d715a in QDialog::~QDialog() qdialog.cpp:357
    #4 0x2ba109854c4b in QFileDialog::~QFileDialog() qfiledialog.cpp:380
    #5 0x4179dc in tst_QFiledialog::init() tst_qfiledialog.cpp:175

Fix by replacing Q_Q with the the equivalent expression for QDialog.

We can't re-use QDialogPrivate::q_func() here, since that is private,
and probably should stay like that.

Also fix an invalid member call in
QColorDialogPrivate::canBeNativeDialog():

  qcolordialog.cpp:2050:5: runtime error: member call on address 0x7ffdf50c1ec0 which does not point to an object of type 'QColorDialog'
  0x7ffdf50c1ec0: note: object is of type 'QDialog'
   fd 7f 00 00  d8 6e c7 23 b7 2a 00 00  50 c1 af 01 00 00 00 00  b0 70 c7 23 b7 2a 00 00  00 00 1a 1e
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QDialog'
    #0 0x2ab720e4e5ea in QColorDialog::options() const qcolordialog.cpp:2050
    #1 0x2ab720e4e8c8 in QColorDialogPrivate::canBeNativeDialog() const qcolordialog.cpp:1870
    #2 0x2ab720e84ed6 in QDialog::setVisible(bool) qdialog.cpp:696
    #3 0x2ab720e6c1fa in QDialog::~QDialog() qdialog.cpp:357
    #4 0x2ab720e2b276 in QColorDialog::~QColorDialog() qcolordialog.cpp:2187
    #5 0x2ab720e5e2c6 in QColorDialog::getColor(QColor const&, QWidget*, QString const&, QFlags<QColorDialog::ColorDialogOption>) qcolordialog.cpp:2148
    #6 0x2ab720e5e473 in QColorDialog::getRgba(unsigned int, bool*, QWidget*) qcolordialog.cpp:2176
    #7 0x407180 in tst_QColorDialog::testGetRgba() tst_qcolordialog.cpp:118

by accessing the data member directly instead of through the Public API.

Fix the same code in QFileDialog, even though the autotest coverage is
too limited for UBSan to point that one out explicitly.

This commit amends abe8b4a, in which
it should have been included in the first place...

Change-Id: Iff0538eba61d2381359f0b61f35918d643f7aa0c
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
qtprojectorg pushed a commit that referenced this pull request Sep 27, 2016
Found by UBSan:

  qlayout.cpp:612:50: runtime error: downcast of address 0x7ffcd4c39a70 which does not point to an object of type 'QWidget'
  0x7ffcd4c39a70: note: object is of type 'QObject'
   00 00 00 00  b0 43 4c 7b f5 2a 00 00  70 c9 28 02 00 00 00 00  08 93 9a 77 f5 2a 00 00  00 00 c3 d4
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QObject'
    #0 0x2af56f189960 in QLayout::widgetEvent(QEvent*) qlayout.cpp:612
    #1 0x2af56f037660 in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3732
    #2 0x2af56f06ae5b in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3704
    #3 0x2af57989e383 in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:988
    #4 0x2af5799c1696 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.h:231
    #5 0x2af5799c1696 in QObjectPrivate::setParent_helper(QObject*) qobject.cpp:2043
    #6 0x2af5799c4823 in QObject::~QObject() qobject.cpp:1095
    #7 0x2af56f2d205d in QWidget::~QWidget() qwidget.cpp:1549
    #8 0x2af56f9c1366 in QFrame::~QFrame() qframe.cpp:262
    #9 0x2af56f9e76cb in QLabel::~QLabel() qlabel.cpp:247
    #10 0x458077 in tst_QStyleSheetStyle::emptyStyleSheet() tst_qstylesheetstyle.cpp:1400

Fix by not casting at all (or, to be precise, casting implicitly up
instead of explicitly down).

Change-Id: Ic19fd29e0cabd1aee5b1c93ca4c0fc70bc7a5927
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
qtprojectorg pushed a commit that referenced this pull request Sep 28, 2016
…nize()

As found by UBSan:

  qstandardgestures.cpp:511:67: runtime error: downcast of address 0x7ffc9beb1b90 which does not point to an object of type 'QTouchEvent'
  0x7ffc9beb1b90: note: object is of type 'QPlatformSurfaceEvent'
   fc 7f 00 00  08 93 b1 6f f5 2a 00 00  00 00 00 00 00 00 00 00  d9 00 ec 9b 00 00 00 00  49 01 c1 5e
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QPlatformSurfaceEvent'
    #0 0x2af55edfa66a in QTapAndHoldGestureRecognizer::recognize(QGesture*, QObject*, QEvent*) qstandardgestures.cpp:511
    #1 0x2af55ee3d9bb in QGestureManager::filterEventThroughContexts(QMultiMap<QObject*, Qt::GestureType> const&, QEvent*) qgesturemanager.cpp:276
    #2 0x2af55ee4565b in QGestureManager::filterEvent(QWidget*, QEvent*) qgesturemanager.cpp:512
    #3 0x2af55ee53945 in QGestureManager::filterEvent(QObject*, QEvent*) qgesturemanager.cpp:556
    #4 0x2af55ea1b83a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3053
    #5 0x2af573949d0f in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:988
    #6 0x2af56982ff94 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.h:231
    #7 0x2af56982ff94 in QWindowPrivate::create(bool) qwindow.cpp:435
    #8 0x2af55ecd10fe in QWidgetPrivate::create_sys(unsigned long long, bool, bool) qwidget.cpp:1471
    #9 0x2af55ecc770e in QWidget::create(unsigned long long, bool, bool) qwidget.cpp:1333
    #10 0x2af55ed80618 in QWidget::setVisible(bool) qwidget.cpp:8156
    #11 0x4feec4 in tst_QWidget::touchEventsForGesturePendingWidgets() tst_qwidget.cpp:9824

  qstandardgestures.cpp:512:67: runtime error: downcast of address 0x7ffc9beb1b90 which does not point to an object of type 'QMouseEvent'
  0x7ffc9beb1b90: note: object is of type 'QPlatformSurfaceEvent'
   fc 7f 00 00  08 93 b1 6f f5 2a 00 00  00 00 00 00 00 00 00 00  d9 00 ec 9b 00 00 00 00  49 01 c1 5e
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QPlatformSurfaceEvent'
    #0 0x2af55edfaa19 in QTapAndHoldGestureRecognizer::recognize(QGesture*, QObject*, QEvent*) qstandardgestures.cpp:512
    [... skipping common lines ...]

  qstandardgestures.cpp:514:95: runtime error: downcast of address 0x
  0x7ffc9beb1b90: note: object is of type 'QPlatformSurfaceEvent'
   fc 7f 00 00  08 93 b1 6f f5 2a 00 00  00 00 00 00 00 00 00 00  d9 00 ec 9b 00 00 00 0
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QPlatformSurfaceEvent'
    #0 0x2af55edfa966 in QTapAndHoldGestureRecognizer::recognize(QGesture*, QObject*, QEvent*) qstandardgestures.cpp:514
    [... skipping common lines ...]

The problem is that the casts are done outside the switch that
determines the event's type, so for any given event object, at least
any two of the casts are invalid.

This could actually be a real problem, because it's trivial for a
compiler to prove that these three lines unconditionally invoke UB, so
it has all the right in the world to decide to drop the complete rest
of the function, using this line of reasoning:

1. The only way for these three casts not to be UB is if event ==
   nullptr.

2. If event == nullptr, then event->type() invokes UB, so event cannot
   be nullptr.

3. The only way both can be true is if this code path is never
   taken. I can thus assume that

      object == state && event->type() == QEvent::Timer

   is always true, drop the check and execute the if block
   unconditionally (I need to call QEvent::type(), to satisfy the
   as-if-rule, but I needn't check its return value).

Fix by moving the casts where they belong: into each case of the
switch, where the type of the event has been checked to match the
target type of the cast.

Change-Id: I3aee8e213dc19d2f51636bcc5221cc92b3142e58
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
qtprojectorg pushed a commit that referenced this pull request Oct 5, 2016
The slot is invoked from QObject::destroyed(), which is emitted
from ~QObject. By that time the object is no longer a QShortcut,
so the static_cast it invalid.

Found by UBSan:

  tst_qshortcut.cpp:1210:53: runtime error: downcast of address 0x6020000289d0 which does not point to an object of type 'QShortcut'
  0x6020000289d0: note: object is of type 'QObject'
   10 00 80 17  c0 ce 63 df 93 2b 00 00  b0 02 00 00 d0 60 00 00  02 00 00 00 ff ff ff 04  04 00 00 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QObject'
    #0 0x42b3bb in tst_QShortcut::shortcutDestroyed(QObject*) tst_qshortcut.cpp:1210
    #1 0x446cc9 in tst_QShortcut::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) .moc/tst_qshortcut.moc:186
    #2 0x2b93dba52c86 in QMetaObject::activate(QObject*, int, int, void**) qobject.cpp:3787
    #3 0x2b93dba55400 in QObject::destroyed(QObject*) .moc/moc_qobject.cpp:213
    #4 0x2b93dba8d80d in QObject::~QObject() qobject.cpp:967
    #5 0x2b93c6b6e032 in QShortcut::~QShortcut() qshortcut.cpp:476
    #6 0x2b93c6b6e370 in QShortcut::~QShortcut() qshortcut.cpp:481
    #7 0x42a5de in void qDeleteAll<QList<QShortcut*>::const_iterator>(QList<QShortcut*>::const_iterator, QList<QShortcut*>::const_iterator) qalgorithms.h:317
    #8 0x42a5de in void qDeleteAll<QList<QShortcut*> >(QList<QShortcut*> const&) qalgorithms.h:325
    #9 0x42a5de in tst_QShortcut::clearAllShortcuts() tst_qshortcut.cpp:1136

Fix by replacing QVector::replaceAll() with the erase-remove idiom,
which does not require the cast, because it can perform mixed-type
lookups.

Change-Id: I4251c1895fa4398023f489dbfd7108d90c1a6c94
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
qtprojectorg pushed a commit that referenced this pull request Oct 6, 2016
Found by UBSan:

  qgraphicswidget_p.h:72:5: runtime error: downcast of address 0x2ab6a8021400 which does not point to an object of type 'QGraphicsWidget'
  0x2ab6a8021400: note: object is of type 'QGraphicsObject'
   00 00 00 00  70 93 5c 91 b6 2a 00 00  f0 c0 01 a8 b6 2a 00 00  e8 81 5c 91 b6 2a 00 00  10 bf 01 a8
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QGraphicsObject'
    #0 0x2ab68f2fdd7c in QGraphicsWidgetPrivate::q_func() qgraphicswidget_p.h:72
    #1 0x2ab68f2fdd7c in QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget*, QGraphicsScene*, QGraphicsScene*) qgraphicswidget_p.cpp:775
    #2 0x2ab68f020d2a in QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem*, QVariant const*, QVariant const*) qgraphicsitem.cpp:1181
    #3 0x2ab68f024f73 in QGraphicsItem::setParentItem(QGraphicsItem*) qgraphicsitem.cpp:1781
    #4 0x2ab68f168401 in QGraphicsScenePrivate::removeItemHelper(QGraphicsItem*) qgraphicsscene.cpp:620
    #5 0x2ab68f02c166 in QGraphicsItem::~QGraphicsItem() qgraphicsitem.cpp:1555
    #6 0x2ab68f02ebb8 in QGraphicsObject::~QGraphicsObject() qgraphicsitem.cpp:7766
    #7 0x2ab68f2d8888 in QGraphicsWidget::~QGraphicsWidget() qgraphicswidget.cpp:231
    #8 0x4bce62 in SubQGraphicsWidget::~SubQGraphicsWidget() /tst_qgraphicswidget.cpp:175
    #9 0x4bce62 in SubQGraphicsWidget::~SubQGraphicsWidget() /tst_qgraphicswidget.cpp:175
    #10 0x2ab68f02c9ec in QGraphicsItem::~QGraphicsItem() qgraphicsitem.cpp:1550
    #11 0x2ab68f02ebb8 in QGraphicsObject::~QGraphicsObject() qgraphicsitem.cpp:7766
    #12 0x2ab68f2d8888 in QGraphicsWidget::~QGraphicsWidget() qgraphicswidget.cpp:231
    #13 0x4bce62 in SubQGraphicsWidget::~SubQGraphicsWidget() /tst_qgraphicswidget.cpp:175
    #14 0x4bce62 in SubQGraphicsWidget::~SubQGraphicsWidget() /tst_qgraphicswidget.cpp:175
    #15 0x2ab68f128da4 in QGraphicsScene::clear() qgraphicsscene.cpp:2388
    #16 0x2ab68f12936c in QGraphicsScene::~QGraphicsScene() qgraphicsscene.cpp:1682
    #17 0x44d44c in tst_QGraphicsWidget::focusWidget() /tst_qgraphicswidget.cpp:435

  qgraphicswidget_p.cpp:805:24: runtime error: member call on address 0x2ab6a8021400 which does not point to an object of type 'QGraphicsWidget'
  0x2ab6a8021400: note: object is of type 'QGraphicsObject'
   00 00 00 00  70 93 5c 91 b6 2a 00 00  f0 c0 01 a8 b6 2a 00 00  e8 81 5c 91 b6 2a 00 00  10 bf 01 a8
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QGraphicsObject'
    #0 0x2ab68f2fdc68 in QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget*, QGraphicsScene*, QGraphicsScene*) qgraphicswidget_p.cpp:805
    #1 0x2ab68f020d2a in QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem*, QVariant const*, QVariant const*) qgraphicsitem.cpp:1181
    [... identical lines omitted ...]

  qgraphicswidget_p.cpp:806:23: runtime error: member call on address 0x2ab6a8021400 which does not point to an object of type 'QGraphicsWidget'
  0x2ab6a8021400: note: object is of type 'QGraphicsObject'
   00 00 00 00  70 93 5c 91 b6 2a 00 00  f0 c0 01 a8 b6 2a 00 00  e8 81 5c 91 b6 2a 00 00  10 bf 01 a8
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QGraphicsObject'
    #0 0x2ab68f2fdb6b in QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget*, QGraphicsScene*, QGraphicsScene*) qgraphicswidget_p.cpp:806
    #1 0x2ab68f020d2a in QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem*, QVariant const*, QVariant const*) qgraphicsitem.cpp:1181
    [... identical lines omitted ...]

  qgraphicswidget_p.cpp:827:26: runtime error: member call on address 0x2ab6a8021400 which does not point to an object of type 'QGraphicsWidget'
  0x2ab6a8021400: note: object is of type 'QGraphicsObject'
   00 00 00 00  70 93 5c 91 b6 2a 00 00  f0 c0 01 a8 b6 2a 00 00  e8 81 5c 91 b6 2a 00 00  10 bf 01 a8
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QGraphicsObject'
    #0 0x2ab68f2fdf91 in QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget*, QGraphicsScene*, QGraphicsScene*) qgraphicswidget_p.cpp:827
    #1 0x2ab68f020d2a in QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem*, QVariant const*, QVariant const*) qgraphicsitem.cpp:1181
    [... identical lines omitted ...]

Fix by moving the setParentItem(nullptr) call up the call stack
into ~QGraphicsWidget(), ensuring that the object is still a
QGraphicsWidget when these calls are made.

Change-Id: I264779e33098e9752de9a312a146fb203578a3cc
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
qtprojectorg pushed a commit that referenced this pull request Oct 12, 2016
…ventFilter()

Found by UBSan:

  tst_qwidget.cpp:10207:29: runtime error: member access within address 0x6060000e8880 which does not point to an object of type 'EnterTestModalDialog'
  0x6060000e8880: note: object is of type 'QWidget'
   eb 00 80 45  10 4b 32 ab 11 2b 00 00  80 df 08 00 60 61 00 00  c0 4c 32 ab 11 2b 00 00  00 00 be be
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QWidget'
    #0 0x6ca13f in EnterTestMainDialog::eventFilter(QObject*, QEvent*) tst_qwidget.cpp:10207
    #1 0x2b11b8bc90c3 in QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject*, QEvent*) qcoreapplication.cpp:1081
    #2 0x2b11a3c49b4a in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3716
    #3 0x2b11a3c8ec72 in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3704
    #4 0x2b11b8bccd0f in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:988
    #5 0x2b11aea5c34d in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.h:231
    #6 0x2b11aea5c34d in QGuiApplicationPrivate::_q_updateFocusObject(QObject*) qguiapplication.cpp:3690
    #7 0x2b11aea61360 in QGuiApplication::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) .moc/moc_qguiapplication.cpp:177
    #8 0x2b11b8d1dc86 in QMetaObject::activate(QObject*, int, int, void**) qobject.cpp:3787
    #9 0x2b11aea784a3 in QWindow::focusObjectChanged(QObject*) .moc/moc_qwindow.cpp:760
    #10 0x2b11a3fb24f2 in QWidget::clearFocus() qwidget.cpp:6705
    #11 0x2b11a3fc87b1 in QWidget::~QWidget() qwidget.cpp:1608
    #12 0x2b11a526688c in QDialog::~QDialog() qdialog.cpp:352
    #13 0x6c43e2 in EnterTestModalDialog::~EnterTestModalDialog() tst_qwidget.cpp:10160
    #14 0x6c43e2 in EnterTestModalDialog::~EnterTestModalDialog() tst_qwidget.cpp:10160
    #15 0x492be3 in EnterTestMainDialog::buttonPressed() tst_qwidget.cpp:10188
    #16 0x492be3 in EnterTestMainDialog::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) .moc/tst_qwidget.moc:2056
    #17 0x2b11b8d1dc86 in QMetaObject::activate(QObject*, int, int, void**) qobject.cpp:3787
    #18 0x2b11a45cb833 in QAbstractButton::clicked(bool) .moc/moc_qabstractbutton.cpp:307
    #19 0x2b11a45cd54b in QAbstractButtonPrivate::emitClicked() qabstractbutton.cpp:411
    #20 0x2b11a45df73a in QAbstractButtonPrivate::click() qabstractbutton.cpp:404
    [...]
    #41 0x6bb2cf in tst_QWidget::taskQTBUG_27643_enterEvents() tst_qwidget.cpp:10249
    [...]

Fix by checking the event type first, and accessing
modal->button only if it's QEvent::Enter.

Change-Id: I2c7df3a1f43ecbfe14741b5861729078a91a32d6
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
qtprojectorg pushed a commit that referenced this pull request Oct 20, 2016
Found by UBSan:

  qnetworkreplyhttpimpl.cpp:457:29: runtime error: member call on address 0x602000009cf0 which does not point to an object of type 'QNetworkReplyHttpImpl'
  0x602000009cf0: note: object is of type 'QObject'
   1e 00 80 18  20 e0 bb 12 54 7f 00 00  00 f2 00 00 70 61 00 00  02 00 00 00 ff ff ff 06  08 00 00 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QObject'
    #0 0x7f541461b71b in QNetworkReplyHttpImplPrivate::~QNetworkReplyHttpImplPrivate() qnetworkreplyhttpimpl.cpp:457
    #1 0x7f541461b7f0 in QNetworkReplyHttpImplPrivate::~QNetworkReplyHttpImplPrivate() qnetworkreplyhttpimpl.cpp:458
    #2 0x7f540f26df1a in QScopedPointerDeleter<QObjectData>::cleanup(QObjectData*) qscopedpointer.h:54
    #3 0x7f540f26df1a in QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData> >::~QScopedPointer() qscopedpointer.h:101
    #4 0x7f540f26df1a in QObject::~QObject() qobject.cpp:940
    #5 0x7f540e915f6e in QIODevice::~QIODevice() qiodevice.cpp:416
    #6 0x7f5414599bae in QNetworkReply::~QNetworkReply() qnetworkreply.cpp:444
    #7 0x7f54145e6f5e in QNetworkReplyHttpImpl::~QNetworkReplyHttpImpl() qnetworkreplyhttpimpl.cpp:239
    #8 0x7f54145e6f5e in QNetworkReplyHttpImpl::~QNetworkReplyHttpImpl() qnetworkreplyhttpimpl.cpp:242
    #9 0x7f54144b3539 in void qDeleteAll<QList<QNetworkReply*>::const_iterator>(QList<QNetworkReply*>::const_iterator, QList<QNetworkReply*>::const_iterator) qalgorithms.h:317
    #10 0x7f54144b3539 in void qDeleteAll<QList<QNetworkReply*> >(QList<QNetworkReply*> const&) qalgorithms.h:325
    #11 0x7f54144b3539 in QNetworkAccessManager::~QNetworkAccessManager() qnetworkaccessmanager.cpp:496

Fix by moving the emission of the QNetworkReplyHttpImpl::abortHttpRequest()
signal from ~Private, when the public object is merely a QObject anymore,
to ~QNetworkReplyHttpImpl(), when the public class is still itself.

Change-Id: Ifb3b19f6d180452bdf3fc26f54629ef780a5d9d9
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@theqtcompany.com>
qtprojectorg pushed a commit that referenced this pull request Mar 22, 2017
QString::toUtf8() returns QByteArray, which got implicitly converted to
C strings and promptly deleted. Instead, return the QByteArray to the
caller.

Found by ASAN:
==13935==ERROR: AddressSanitizer: heap-use-after-free on address 0x6060000dffb8 at pc 0x7f764f27320b bp 0x7ffd49b11bb0 sp 0x7ffd49b11358
READ of size 7 at 0x6060000dffb8 thread T0
    #1 0x7f7649d174e2 in g_strdup (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x684e2)
    #2 0x7f763f7abe5b  (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0+0x39e5b)
    #3 0x7f763f78915a in g_object_new_valist (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0+0x1715a)
    #4 0x7f763f789520 in g_object_new (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0+0x17520)
    #5 0x7f7640f6bcb0 in gtk_dialog_add_button (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0+0x186cb0)
    #6 0x7f7640f8d2c9 in gtk_file_chooser_dialog_new (/usr/lib/x86_64-linux-gnu/libgtk-3.so.0+0x1a82c9)
    #7 0x7f7641727281  (/opt/Qt5.8.0/5.8/gcc_64/plugins/platformthemes/libqgtk3.so+0x13281)

Task-number: QTBUG-59611
Change-Id: I37cc967e689f4523b504fffd14adbf944b53b754
Reviewed-by: J-P Nurmi <jpnurmi@qt.io>
qtprojectorg pushed a commit that referenced this pull request Apr 19, 2017
Delete the QGraphicsEffect from the QWidget destructor instead of from
the QWidgetPrivate destructor. The destructor of QGraphicsEffect still
access methods of the QWidget, but the QObjectPrivate being destroyed
from ~QObject, the pointer is no longer a QWidget.

Fix warning with UB sanitizer in tst_QWidget::setGraphicsEffect

qwidget_p.h:900:23: runtime error: member call on address 0x000001d822c0 which does not point to an object of type 'QWidget'
0x000001d822c0: note: object is of type 'QObject'
 00 00 00 00  b0 46 5f 40 e5 7f 00 00  00 23 d8 01 00 00 00 00  f0 e6 00 44 e5 7f 00 00  00 00 74 47
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'QObject'
    #0 0x7fe54767db76 in QWidgetEffectSourcePrivate::detach()
    #1 0x7fe548f29815 in QGraphicsEffect::~QGraphicsEffect()
    #2 0x7fe548f2a1b7 in QGraphicsBlurEffect::~QGraphicsBlurEffect()
    #3 0x7fe548f2a208 in QGraphicsBlurEffect::~QGraphicsBlurEffect()
    #4 0x7fe5475cd463 in QWidgetPrivate::~QWidgetPrivate()
    #5 0x7fe5475ce62c in QWidgetPrivate::~QWidgetPrivate()
    #6 0x7fe5400d0dda in QObject::~QObject()
    #7 0x7fe54763d411 in QWidget::~QWidget()
    #8 0x7fe54763d7f4 in QWidget::~QWidget()
    #9 0x4cc309 in QScopedPointerDeleter<QWidget>::cleanup(QWidget*)
    #10 0x4cc309 in QScopedPointer<QWidget, QScopedPointerDeleter<QWidget> >::reset(QWidget*)
    #11 0x4cc309 in tst_QWidget::setGraphicsEffect()

Change-Id: I19c049e979cfce2adda908af8336cb4adac8f6c4
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
qtprojectorg pushed a commit that referenced this pull request Aug 27, 2017
I'm getting crashes in Akonadi processes due to libproxy. I don't have
direct evidence that this was caused by a threading condition, but it's
clear from the source code of libproxy that the plugins it runs for
expanding PAC scripts are not thread-safe. To overcome this problem, we
only run libproxy functions in one thread only.

 #0  0x00007f745f0ac1d8 in JSC::HeapTimer::timerDidFire() () at /usr/lib64/libjavascriptcoregtk-4.0.so.18
 #1  0x00007f745f0ac287 in  () at /usr/lib64/libjavascriptcoregtk-4.0.so.18
 #2  0x00007f748e5ae9c5 in g_main_context_dispatch () at /usr/lib64/libglib-2.0.so.0
 #3  0x00007f748e5aed88 in  () at /usr/lib64/libglib-2.0.so.0
 #4  0x00007f748e5aee1c in g_main_context_iteration () at /usr/lib64/libglib-2.0.so.0
 #5  0x00007f7494f4268f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib64/libQt5Core.so.5
 #6  0x00007f7494eeb35a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib64/libQt5Core.so.5
 #7  0x00007f7494d1b31a in QThread::exec() () at /usr/lib64/libQt5Core.so.5
 #8  0x00007f7494d1fd2e in  () at /usr/lib64/libQt5Core.so.5
 #9  0x00007f74913174e7 in start_thread () at /lib64/libpthread.so.0

The pacrunner implementation of libproxy uses libdbus-1 which
(officially) is thread-safe, but experience tells that it has
problems. Since it is not running a JS engine, we don't need a thread,
but we do need to lock around it.

Change-Id: I84e45059a888497fb55ffffd14d2f638f21e807d
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
qtprojectorg pushed a commit that referenced this pull request Jun 27, 2018
NSOpenGLContext should be re-entrant, but is not in practice, resulting
in deadlocks when there are two render threads, eg:

 thread #23, name = 'QSGRenderThread'
    frame #0: 0x00007fff5c6dda4e libsystem_kernel.dylib`__psynch_mutexwait + 10
    frame #1: 0x00007fff5c8a5b9d libsystem_pthread.dylib`_pthread_mutex_lock_wait + 83
    frame #2: 0x00007fff5c8a34c8 libsystem_pthread.dylib`_pthread_mutex_lock_slow + 253
    frame #3: 0x00007fff31ebb52e AppKit`flush_notify + 110
    frame #4: 0x00007fff3e75ee2a GLEngine`glSwap_Exec + 186
    frame #5: 0x00007fff3e740797 OpenGL`CGLFlushDrawable + 59
    frame #6: 0x00007fff31ad43ac AppKit`-[NSOpenGLContext flushBuffer] + 27
    ...

Task-number: QTBUG-69040
Change-Id: I6f28b4cc5faf61ae93f66353ce2abdf8c223d994
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
qtprojectorg pushed a commit that referenced this pull request Sep 10, 2018
Calling setView or update on NSOpenGLContext results in recreating the
internal GL surfaces of the view. Unfortunately there seems to be a
fixed amount of these surfaces available, so if we spin a loop where
we for some reason end up recreating them, we'll easily run out, and
lock up the whole window system:

  thread #6, name = 'SwapThread'
    frame #0: 0x00007fff7b45220a libsystem_kernel.dylib`mach_msg_trap + 10
    frame #1: 0x00007fff7b451724 libsystem_kernel.dylib`mach_msg + 60
    frame #2: 0x00007fff751c1675 SkyLight`SLSBindSurface + 247
    frame #3: 0x00007fff5d9c4328 OpenGL`___lldb_unnamed_symbol29$$OpenGL + 255
    frame #4: 0x00007fff6bf42c33 libGPUSupportMercury.dylib`gldAttachDrawable + 364
    frame #5: 0x00007fff5d9e61e7 GLEngine`gliAttachDrawableWithOptions + 257
    frame #6: 0x00007fff5d9c4bb0 OpenGL`___lldb_unnamed_symbol38$$OpenGL + 969
    frame #7: 0x00007fff5d9c8b0e OpenGL`___lldb_unnamed_symbol57$$OpenGL + 82
    frame #8: 0x00007fff5d9c8e55 OpenGL`CGLSetSurface + 330
    frame #9: 0x00007fff50d0eb2c AppKit`NSOpenGLContextAttachOffScreenViewSurface + 352

This can happen e.g. when resizing the application, where AppKit itself spins
a loop where we don't end up back in QCocoaEventDispatcher::processEvents()
for each pass (where we do have a local pool). Or it can happen in the
render-loop of a render-thread that doesn't use the event dispatcher.

Change-Id: Iaf2f879dd01e3d807d0f35705ccc978dbc89036b
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
qtprojectorg pushed a commit that referenced this pull request Sep 26, 2018
By making the hardcoded values unsigned

image/qppmhandler.cpp:126:36: runtime error: signed integer overflow: 65535 * 65535 cannot be represented in type 'int'
    #0 0x4cef10 in scale_pbm_color(unsigned short, unsigned short, unsigned short, unsigned short) /src/qt/qtbase/src/gui/image/qppmhandler.cpp:126:36
    #1 0x4cb1d5 in read_pbm_body(QIODevice*, char, int, int, int, QImage*) /src/qt/qtbase/src/gui/image/qppmhandler.cpp:274:39
    #2 0x4ca3d8 in QPpmHandler::read(QImage*) /src/qt/qtbase/src/gui/image/qppmhandler.cpp:509:10
    #3 0x4b238d in QImageReader::read(QImage*) /src/qt/qtbase/src/gui/image/qimagereader.cpp:1253:22
    #4 0x4b1b61 in QImageReader::read() /src/qt/qtbase/src/gui/image/qimagereader.cpp:1201:12
    #5 0x486f66 in QImage::fromData(unsigned char const*, int, char const*) /src/qt/qtbase/src/gui/image/qimage.cpp:3624:37
    #6 0x486cd8 in QImage::loadFromData(unsigned char const*, int, char const*) /src/qt/qtbase/src/gui/image/qimage.cpp:3590:13
    #7 0x434b2e in LLVMFuzzerTestOneInput /src/qimage_fuzzer.cc:28:7
    #8 0x44b167 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/libfuzzer/FuzzerLoop.cpp:570:15
    #9 0x43c8bd in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/libfuzzer/FuzzerDriver.cpp:280:6
    #10 0x4407bb in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/libfuzzer/FuzzerDriver.cpp:713:9
    #11 0x434bf8 in main /src/libfuzzer/FuzzerMain.cpp:20:10
    #12 0x7fd4d93b982f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #13 0x409bb8 in _start (/out/qimage_fuzzer+0x409bb8)

Change-Id: I56674d0c2e59a30095552eb84aba17d7b516dd4a
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
qtprojectorg pushed a commit that referenced this pull request Oct 5, 2018
image/qppmhandler.cpp:77:25: runtime error: signed integer overflow: 10 * 300000000 cannot be represented in type 'int'
    #0 0x4cecb5 in read_pbm_int(QIODevice*) /src/qt/qtbase/src/gui/image/qppmhandler.cpp:77:25
    #1 0x4cb1ac in read_pbm_body(QIODevice*, char, int, int, int, QImage*) /src/qt/qtbase/src/gui/image/qppmhandler.cpp:271:29
    #2 0x4ca3d8 in QPpmHandler::read(QImage*) /src/qt/qtbase/src/gui/image/qppmhandler.cpp:509:10
    #3 0x4b238d in QImageReader::read(QImage*) /src/qt/qtbase/src/gui/image/qimagereader.cpp:1253:22
    #4 0x4b1b61 in QImageReader::read() /src/qt/qtbase/src/gui/image/qimagereader.cpp:1201:12
    #5 0x486f66 in QImage::fromData(unsigned char const*, int, char const*) /src/qt/qtbase/src/gui/image/qimage.cpp:3624:37
    #6 0x486cd8 in QImage::loadFromData(unsigned char const*, int, char const*) /src/qt/qtbase/src/gui/image/qimage.cpp:3590:13
    #7 0x434b2e in LLVMFuzzerTestOneInput /src/qimage_fuzzer.cc:28:7
    #8 0x44b167 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/libfuzzer/FuzzerLoop.cpp:570:15
    #9 0x44a535 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /src/libfuzzer/FuzzerLoop.cpp:479:3
    #10 0x44c428 in fuzzer::Fuzzer::MutateAndTestOne() /src/libfuzzer/FuzzerLoop.cpp:707:19
    #11 0x44d1b5 in fuzzer::Fuzzer::Loop(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, fuzzer::fuzzer_allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) /src/libfuzzer/FuzzerLoop.cpp:838:5
    #12 0x440a29 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/libfuzzer/FuzzerDriver.cpp:764:6
    #13 0x434bf8 in main /src/libfuzzer/FuzzerMain.cpp:20:10
    #14 0x7fba939a082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #15 0x409bb8 in _start (/out/qimage_fuzzer+0x409bb8)

Change-Id: I9ad78afc4ea9c5c8b7530aa17013abe91202e84b
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
qtprojectorg pushed a commit that referenced this pull request Oct 5, 2018
image/qppmhandler.cpp:260:53: runtime error: signed integer overflow: 44444444 * 255 cannot be represented in type 'int'
    #0 0x4cbc8a in read_pbm_body(QIODevice*, char, int, int, int, QImage*) /src/qt/qtbase/src/gui/image/qppmhandler.cpp:260:53
    #1 0x4ca3d8 in QPpmHandler::read(QImage*) /src/qt/qtbase/src/gui/image/qppmhandler.cpp:514:10
    #2 0x4b238d in QImageReader::read(QImage*) /src/qt/qtbase/src/gui/image/qimagereader.cpp:1253:22
    #3 0x4b1b61 in QImageReader::read() /src/qt/qtbase/src/gui/image/qimagereader.cpp:1201:12
    #4 0x486f66 in QImage::fromData(unsigned char const*, int, char const*) /src/qt/qtbase/src/gui/image/qimage.cpp:3624:37
    #5 0x486cd8 in QImage::loadFromData(unsigned char const*, int, char const*) /src/qt/qtbase/src/gui/image/qimage.cpp:3590:13
    #6 0x434b2e in LLVMFuzzerTestOneInput /src/qimage_fuzzer.cc:28:7
    #7 0x44b167 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/libfuzzer/FuzzerLoop.cpp:570:15
    #8 0x44a535 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /src/libfuzzer/FuzzerLoop.cpp:479:3
    #9 0x44c428 in fuzzer::Fuzzer::MutateAndTestOne() /src/libfuzzer/FuzzerLoop.cpp:707:19
    #10 0x44d1b5 in fuzzer::Fuzzer::Loop(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, fuzzer::fuzzer_allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) /src/libfuzzer/FuzzerLoop.cpp:838:5
    #11 0x440a29 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/libfuzzer/FuzzerDriver.cpp:764:6
    #12 0x434bf8 in main /src/libfuzzer/FuzzerMain.cpp:20:10
    #13 0x7fe01697282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #14 0x409bb8 in _start (/out/qimage_fuzzer+0x409bb8)

Change-Id: Ibc5df6db52639f12319910b927f6443d927206d8
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
qtprojectorg pushed a commit that referenced this pull request Nov 9, 2018
It crashes in the render thread:

thread #7, name = 'SceneRenderingThread'
   frame #0: libsystem_kernel.dylib`__wait4_nocancel + 10
   frame #1: libsystem_c.dylib`system + 452
   frame #2: QtTest`stackTrace() + 325
   frame #3: QtTest`QTest::FatalSignalHandler::signal(int) + 207
   frame #4: libsystem_platform.dylib`_sigtramp + 26
   frame #5: libsystem_platform.dylib`_platform_bzero$VARIANT$Base + 23
   frame #6: GLRendererFloat`gldSetZero + 63
   frame #7: GLRendererFloat`gldClearDrawBuffer + 3792
   frame #8: GLRendererFloat`gldClearFramebufferData + 49
   frame #9: GLEngine`glClear_Exec + 541
   frame #10: tst_qglthreads`SceneRenderingThread::run() + 227

Task-number: QTBUG-68524
Change-Id: I6bc67cb342f77dc1a590a25af535f9bb7f0d325a
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
qtprojectorg pushed a commit that referenced this pull request Sep 17, 2021
We can't guarantee that the library didn't define Objective-C classes
that still have lingering references, resulting in warnings such as:

 Attempt to use unknown class 0x10e52e110.

And possibly crashes such as:

 thread #1, queue = 'com.apple.main-thread'
    frame #0: 0x00007fff203829ee libsystem_kernel.dylib`__ulock_wait + 10
    frame #1: 0x00007fff203fa0c5 libsystem_platform.dylib`_os_unfair_lock_lock_slow + 162
    frame #2: 0x00007fff2026226b libobjc.A.dylib`unmap_image + 85
    frame #3: 0x000000010001e11f dyld`dyld::removeImage(ImageLoader*) + 557
    frame #4: 0x000000010002291d dyld`dyld::garbageCollectImages() + 956
    frame #5: 0x000000010002e35d dyld`dlclose + 191
    frame #6: 0x00007fff203cf1c9 libdyld.dylib`dlclose + 183
    frame #7: 0x0000000103f9f2f1 libQt6Core_debug.6.dylib`QLibraryPrivate::unload_sys(this=0x000000011ba2c7d0) at qlibrary_unix.cpp:294:9
    frame #8: 0x0000000103f93f3f libQt6Core_debug.6.dylib`QLibraryPrivate::unload(this=0x000000011ba2c7d0, flag=UnloadSys) at qlibrary.cpp:614:36
    frame #9: 0x0000000103f971fb libQt6Core_debug.6.dylib`QLibraryStore::cleanup() at qlibrary.cpp:425:22
    frame #10: 0x0000000103f970f9 libQt6Core_debug.6.dylib`qlibraryCleanup() at qlibrary.cpp:447:5
    frame #11: 0x0000000103f970d1 libQt6Core_debug.6.dylib`(anonymous namespace)::qlibraryCleanup_dtor_class_::~qlibraryCleanup_dtor_class_(this=0x00000001041edd38) at qlibrary.cpp:449:1
    frame #12: 0x0000000103f930f5 libQt6Core_debug.6.dylib`(anonymous namespace)::qlibraryCleanup_dtor_class_::~qlibraryCleanup_dtor_class_(this=0x00000001041edd38) at qlibrary.cpp:449:1
    frame #13: 0x00007fff202e5d25 libsystem_c.dylib`__cxa_finalize_ranges + 316
    frame #14: 0x00007fff202e6010 libsystem_c.dylib`exit + 53
    frame #15: 0x00007fff203d1f44 libdyld.dylib`start + 8
    frame #16: 0x00007fff203d1f3d libdyld.dylib`start + 1

  thread #5, queue = 'com.apple.root.user-interactive-qos', stop reason = signal SIGABRT
    frame #0: 0x00007fff203a356e libsystem_kernel.dylib`__abort_with_payload + 10
    frame #1: 0x00007fff203a4fbd libsystem_kernel.dylib`abort_with_payload_wrapper_internal + 80
    frame #2: 0x00007fff203a4f6d libsystem_kernel.dylib`abort_with_reason + 19
    frame #3: 0x00007fff202749e3 libobjc.A.dylib`_objc_fatalv(unsigned long long, unsigned long long, char const*, __va_list_tag*) + 114
    frame #4: 0x00007fff20274971 libobjc.A.dylib`_objc_fatal(char const*, ...) + 135
    frame #5: 0x00007fff20255ccb libobjc.A.dylib`lookUpImpOrForward + 881
    frame #6: 0x00007fff2025539b libobjc.A.dylib`_objc_msgSend_uncached + 75
    frame #7: 0x00007fff22f368d6 AppKit`-[_NSWindowTransformAnimation setCurrentProgress:] + 42
    frame #8: 0x00007fff22f37a8a AppKit`__55-[NSAnimation(NSInternal) _advanceTimeWithDisplayLink:]_block_invoke + 31
    frame #9: 0x00007fff22d0774f AppKit`NSPerformVisuallyAtomicChange + 132
    frame #10: 0x00007fff22f379dc AppKit`-[NSAnimation(NSInternal) _advanceTimeWithDisplayLink:] + 172
    frame #11: 0x00007fff22e9a184 AppKit`-[NSScreenDisplayLink _fire] + 180
    frame #12: 0x00007fff2362f0b4 AppKit`___NSRunLoopTimerCreateWithHandler_block_invoke + 34
    frame #13: 0x00007fff204c6be9 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
    frame #14: 0x00007fff204c66dd CoreFoundation`__CFRunLoopDoTimer + 927
    frame #15: 0x00007fff204c623a CoreFoundation`__CFRunLoopDoTimers + 307
    frame #16: 0x00007fff204ace13 CoreFoundation`__CFRunLoopRun + 1988
    frame #17: 0x00007fff204abf8c CoreFoundation`CFRunLoopRunSpecific + 563
    frame #18: 0x00007fff2123d607 Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212
    frame #19: 0x00007fff22f378f0 AppKit`-[NSAnimation(NSInternal) _runBlocking] + 453
    frame #20: 0x00007fff22f376ae AppKit`__42-[NSAnimation(NSInternal) _runInNewThread]_block_invoke + 97
    frame #21: 0x0000000104edb032 libdispatch.dylib`_dispatch_call_block_and_release + 12
    frame #22: 0x0000000104edc264 libdispatch.dylib`_dispatch_client_callout + 8
    frame #23: 0x0000000104ef04ac libdispatch.dylib`_dispatch_root_queue_drain + 828
    frame #24: 0x0000000104ef0d3f libdispatch.dylib`_dispatch_worker_thread2 + 127
    frame #25: 0x0000000104f7eac7 libsystem_pthread.dylib`_pthread_wqthread + 244
    frame #26: 0x0000000104f7dae3 libsystem_pthread.dylib`start_wqthread + 15

This has been e.g. observed when a QNSWindow isn't closed and released
at application quit as expected. Although that is a corner case that
shouldn't happen, the general case is still valid.

Fixes: QTBUG-96208
Pick-to: 6.2 5.15
Change-Id: I6c9d220e6f5389707baf7ae983f3156e8e51c316
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
qtprojectorg pushed a commit that referenced this pull request Sep 17, 2021
We can't guarantee that the library didn't define Objective-C classes
that still have lingering references, resulting in warnings such as:

 Attempt to use unknown class 0x10e52e110.

And possibly crashes such as:

 thread #1, queue = 'com.apple.main-thread'
    frame #0: 0x00007fff203829ee libsystem_kernel.dylib`__ulock_wait + 10
    frame #1: 0x00007fff203fa0c5 libsystem_platform.dylib`_os_unfair_lock_lock_slow + 162
    frame #2: 0x00007fff2026226b libobjc.A.dylib`unmap_image + 85
    frame #3: 0x000000010001e11f dyld`dyld::removeImage(ImageLoader*) + 557
    frame #4: 0x000000010002291d dyld`dyld::garbageCollectImages() + 956
    frame #5: 0x000000010002e35d dyld`dlclose + 191
    frame #6: 0x00007fff203cf1c9 libdyld.dylib`dlclose + 183
    frame #7: 0x0000000103f9f2f1 libQt6Core_debug.6.dylib`QLibraryPrivate::unload_sys(this=0x000000011ba2c7d0) at qlibrary_unix.cpp:294:9
    frame #8: 0x0000000103f93f3f libQt6Core_debug.6.dylib`QLibraryPrivate::unload(this=0x000000011ba2c7d0, flag=UnloadSys) at qlibrary.cpp:614:36
    frame #9: 0x0000000103f971fb libQt6Core_debug.6.dylib`QLibraryStore::cleanup() at qlibrary.cpp:425:22
    frame #10: 0x0000000103f970f9 libQt6Core_debug.6.dylib`qlibraryCleanup() at qlibrary.cpp:447:5
    frame #11: 0x0000000103f970d1 libQt6Core_debug.6.dylib`(anonymous namespace)::qlibraryCleanup_dtor_class_::~qlibraryCleanup_dtor_class_(this=0x00000001041edd38) at qlibrary.cpp:449:1
    frame #12: 0x0000000103f930f5 libQt6Core_debug.6.dylib`(anonymous namespace)::qlibraryCleanup_dtor_class_::~qlibraryCleanup_dtor_class_(this=0x00000001041edd38) at qlibrary.cpp:449:1
    frame #13: 0x00007fff202e5d25 libsystem_c.dylib`__cxa_finalize_ranges + 316
    frame #14: 0x00007fff202e6010 libsystem_c.dylib`exit + 53
    frame #15: 0x00007fff203d1f44 libdyld.dylib`start + 8
    frame #16: 0x00007fff203d1f3d libdyld.dylib`start + 1

  thread #5, queue = 'com.apple.root.user-interactive-qos', stop reason = signal SIGABRT
    frame #0: 0x00007fff203a356e libsystem_kernel.dylib`__abort_with_payload + 10
    frame #1: 0x00007fff203a4fbd libsystem_kernel.dylib`abort_with_payload_wrapper_internal + 80
    frame #2: 0x00007fff203a4f6d libsystem_kernel.dylib`abort_with_reason + 19
    frame #3: 0x00007fff202749e3 libobjc.A.dylib`_objc_fatalv(unsigned long long, unsigned long long, char const*, __va_list_tag*) + 114
    frame #4: 0x00007fff20274971 libobjc.A.dylib`_objc_fatal(char const*, ...) + 135
    frame #5: 0x00007fff20255ccb libobjc.A.dylib`lookUpImpOrForward + 881
    frame #6: 0x00007fff2025539b libobjc.A.dylib`_objc_msgSend_uncached + 75
    frame #7: 0x00007fff22f368d6 AppKit`-[_NSWindowTransformAnimation setCurrentProgress:] + 42
    frame #8: 0x00007fff22f37a8a AppKit`__55-[NSAnimation(NSInternal) _advanceTimeWithDisplayLink:]_block_invoke + 31
    frame #9: 0x00007fff22d0774f AppKit`NSPerformVisuallyAtomicChange + 132
    frame #10: 0x00007fff22f379dc AppKit`-[NSAnimation(NSInternal) _advanceTimeWithDisplayLink:] + 172
    frame #11: 0x00007fff22e9a184 AppKit`-[NSScreenDisplayLink _fire] + 180
    frame #12: 0x00007fff2362f0b4 AppKit`___NSRunLoopTimerCreateWithHandler_block_invoke + 34
    frame #13: 0x00007fff204c6be9 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
    frame #14: 0x00007fff204c66dd CoreFoundation`__CFRunLoopDoTimer + 927
    frame #15: 0x00007fff204c623a CoreFoundation`__CFRunLoopDoTimers + 307
    frame #16: 0x00007fff204ace13 CoreFoundation`__CFRunLoopRun + 1988
    frame #17: 0x00007fff204abf8c CoreFoundation`CFRunLoopRunSpecific + 563
    frame #18: 0x00007fff2123d607 Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212
    frame #19: 0x00007fff22f378f0 AppKit`-[NSAnimation(NSInternal) _runBlocking] + 453
    frame #20: 0x00007fff22f376ae AppKit`__42-[NSAnimation(NSInternal) _runInNewThread]_block_invoke + 97
    frame #21: 0x0000000104edb032 libdispatch.dylib`_dispatch_call_block_and_release + 12
    frame #22: 0x0000000104edc264 libdispatch.dylib`_dispatch_client_callout + 8
    frame #23: 0x0000000104ef04ac libdispatch.dylib`_dispatch_root_queue_drain + 828
    frame #24: 0x0000000104ef0d3f libdispatch.dylib`_dispatch_worker_thread2 + 127
    frame #25: 0x0000000104f7eac7 libsystem_pthread.dylib`_pthread_wqthread + 244
    frame #26: 0x0000000104f7dae3 libsystem_pthread.dylib`start_wqthread + 15

This has been e.g. observed when a QNSWindow isn't closed and released
at application quit as expected. Although that is a corner case that
shouldn't happen, the general case is still valid.

Fixes: QTBUG-96208
Change-Id: I6c9d220e6f5389707baf7ae983f3156e8e51c316
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
(cherry picked from commit b6200de)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
sh-zam added a commit to sh-zam/qtbase that referenced this pull request Mar 10, 2022
********** Crash dump: **********
#00 0x0000000000592f8c /apex/com.android.runtime/lib64/libart.so (artQuickToInterpreterBridge+1036) (BuildId: a5b81c452e2ce0b9c64167ee12585bec)
qt#1 0x0000000000140468 /apex/com.android.runtime/lib64/libart.so (art_quick_to_interpreter_bridge+88) (BuildId: a5b81c452e2ce0b9c64167ee12585bec)
qt#2 0x000000000201598c /memfd:/jit-cache (deleted) (android.view.GestureDetector.onTouchEvent+4268)
qt#3 0x00000000020188ac /memfd:/jit-cache (deleted) (org.qtproject.qt5.android.QtLayout.onTouchEvent+108)
qt#4 0x00000000020161d4 /memfd:/jit-cache (deleted) (android.view.View.dispatchTouchEvent+996)
qt#5 0x000000000201333c /memfd:/jit-cache (deleted) (android.view.ViewGroup.dispatchTransformedTouchEvent+252)
qt#6 0x0000000002012d08 /memfd:/jit-cache (deleted) (android.view.ViewGroup.dispatchTouchEvent+4104)
qt#7 0x0000000002013394 /memfd:/jit-cache (deleted) (android.view.ViewGroup.dispatchTransformedTouchEvent+340)
qt#8 0x00000000020129e4 /memfd:/jit-cache (deleted) (android.view.ViewGroup.dispatchTouchEvent+3300)
qt#9 0x0000000002013394 /memfd:/jit-cache (deleted) (android.view.ViewGroup.dispatchTransformedTouchEvent+340)
[...]
qtprojectorg pushed a commit that referenced this pull request Oct 27, 2022
We can't guarantee that the library didn't define Objective-C classes
that still have lingering references, resulting in warnings such as:

 Attempt to use unknown class 0x10e52e110.

And possibly crashes such as:

 thread #1, queue = 'com.apple.main-thread'
    frame #0: 0x00007fff203829ee libsystem_kernel.dylib`__ulock_wait + 10
    frame #1: 0x00007fff203fa0c5 libsystem_platform.dylib`_os_unfair_lock_lock_slow + 162
    frame #2: 0x00007fff2026226b libobjc.A.dylib`unmap_image + 85
    frame #3: 0x000000010001e11f dyld`dyld::removeImage(ImageLoader*) + 557
    frame #4: 0x000000010002291d dyld`dyld::garbageCollectImages() + 956
    frame #5: 0x000000010002e35d dyld`dlclose + 191
    frame #6: 0x00007fff203cf1c9 libdyld.dylib`dlclose + 183
    frame #7: 0x0000000103f9f2f1 libQt6Core_debug.6.dylib`QLibraryPrivate::unload_sys(this=0x000000011ba2c7d0) at qlibrary_unix.cpp:294:9
    frame #8: 0x0000000103f93f3f libQt6Core_debug.6.dylib`QLibraryPrivate::unload(this=0x000000011ba2c7d0, flag=UnloadSys) at qlibrary.cpp:614:36
    frame #9: 0x0000000103f971fb libQt6Core_debug.6.dylib`QLibraryStore::cleanup() at qlibrary.cpp:425:22
    frame #10: 0x0000000103f970f9 libQt6Core_debug.6.dylib`qlibraryCleanup() at qlibrary.cpp:447:5
    frame #11: 0x0000000103f970d1 libQt6Core_debug.6.dylib`(anonymous namespace)::qlibraryCleanup_dtor_class_::~qlibraryCleanup_dtor_class_(this=0x00000001041edd38) at qlibrary.cpp:449:1
    frame #12: 0x0000000103f930f5 libQt6Core_debug.6.dylib`(anonymous namespace)::qlibraryCleanup_dtor_class_::~qlibraryCleanup_dtor_class_(this=0x00000001041edd38) at qlibrary.cpp:449:1
    frame #13: 0x00007fff202e5d25 libsystem_c.dylib`__cxa_finalize_ranges + 316
    frame #14: 0x00007fff202e6010 libsystem_c.dylib`exit + 53
    frame #15: 0x00007fff203d1f44 libdyld.dylib`start + 8
    frame #16: 0x00007fff203d1f3d libdyld.dylib`start + 1

  thread #5, queue = 'com.apple.root.user-interactive-qos', stop reason = signal SIGABRT
    frame #0: 0x00007fff203a356e libsystem_kernel.dylib`__abort_with_payload + 10
    frame #1: 0x00007fff203a4fbd libsystem_kernel.dylib`abort_with_payload_wrapper_internal + 80
    frame #2: 0x00007fff203a4f6d libsystem_kernel.dylib`abort_with_reason + 19
    frame #3: 0x00007fff202749e3 libobjc.A.dylib`_objc_fatalv(unsigned long long, unsigned long long, char const*, __va_list_tag*) + 114
    frame #4: 0x00007fff20274971 libobjc.A.dylib`_objc_fatal(char const*, ...) + 135
    frame #5: 0x00007fff20255ccb libobjc.A.dylib`lookUpImpOrForward + 881
    frame #6: 0x00007fff2025539b libobjc.A.dylib`_objc_msgSend_uncached + 75
    frame #7: 0x00007fff22f368d6 AppKit`-[_NSWindowTransformAnimation setCurrentProgress:] + 42
    frame #8: 0x00007fff22f37a8a AppKit`__55-[NSAnimation(NSInternal) _advanceTimeWithDisplayLink:]_block_invoke + 31
    frame #9: 0x00007fff22d0774f AppKit`NSPerformVisuallyAtomicChange + 132
    frame #10: 0x00007fff22f379dc AppKit`-[NSAnimation(NSInternal) _advanceTimeWithDisplayLink:] + 172
    frame #11: 0x00007fff22e9a184 AppKit`-[NSScreenDisplayLink _fire] + 180
    frame #12: 0x00007fff2362f0b4 AppKit`___NSRunLoopTimerCreateWithHandler_block_invoke + 34
    frame #13: 0x00007fff204c6be9 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
    frame #14: 0x00007fff204c66dd CoreFoundation`__CFRunLoopDoTimer + 927
    frame #15: 0x00007fff204c623a CoreFoundation`__CFRunLoopDoTimers + 307
    frame #16: 0x00007fff204ace13 CoreFoundation`__CFRunLoopRun + 1988
    frame #17: 0x00007fff204abf8c CoreFoundation`CFRunLoopRunSpecific + 563
    frame #18: 0x00007fff2123d607 Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212
    frame #19: 0x00007fff22f378f0 AppKit`-[NSAnimation(NSInternal) _runBlocking] + 453
    frame #20: 0x00007fff22f376ae AppKit`__42-[NSAnimation(NSInternal) _runInNewThread]_block_invoke + 97
    frame #21: 0x0000000104edb032 libdispatch.dylib`_dispatch_call_block_and_release + 12
    frame #22: 0x0000000104edc264 libdispatch.dylib`_dispatch_client_callout + 8
    frame #23: 0x0000000104ef04ac libdispatch.dylib`_dispatch_root_queue_drain + 828
    frame #24: 0x0000000104ef0d3f libdispatch.dylib`_dispatch_worker_thread2 + 127
    frame #25: 0x0000000104f7eac7 libsystem_pthread.dylib`_pthread_wqthread + 244
    frame #26: 0x0000000104f7dae3 libsystem_pthread.dylib`start_wqthread + 15

This has been e.g. observed when a QNSWindow isn't closed and released
at application quit as expected. Although that is a corner case that
shouldn't happen, the general case is still valid.

Fixes: QTBUG-96208
Change-Id: I6c9d220e6f5389707baf7ae983f3156e8e51c316
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
(cherry picked from commit b6200de)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
qtprojectorg pushed a commit that referenced this pull request Apr 29, 2023
The result is retained so long as we don't attempt to change our locale,
but failing to change that is the reason why we printed anything.

==20227==ERROR: AddressSanitizer: heap-use-after-free on address 0x000107312696 at pc 0x000103c48088 bp 0x00016ee180c0 sp 0x00016ee17880
READ of size 9 at 0x000107312696 thread T0
    #0 0x103c48084 in wrap_strlen+0x164 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x18084) (BuildId: f0a7ac5c49bc3abc851181b6f92b308a32000000200000000100000000000b00)
    #1 0x1023804bc in QString::vasprintf(char const*, char*) qstring.cpp:7112
    #2 0x102243578 in qt_message(QtMsgType, QMessageLogContext const&, char const*, char*) qlogging.cpp:368
    #3 0x10252630c in QMessageLogger::warning(char const*, ...) const qlogging.cpp:647
    #4 0x10229f940 in QCoreApplicationPrivate::initLocale() qcoreapplication.cpp:664
    #5 0x10229fba0 in QCoreApplicationPrivate::init() qcoreapplication.cpp:826
    #6 0x1022a07c0 in QCoreApplication::QCoreApplication(int&, char**, int) qcoreapplication.cpp:799
    #7 0x101454ef8 in main+0xeb0 (WSgen:arm64+0x100470ef8) (BuildId: ae9b4fec1fd73c1693047a6b9d9ce91432000000200000000100000000000b00)

Pick-to: 6.5
Task-number: QTBUG-111443
Change-Id: I6f518d59e63249ddbf43fffd1759d28738124797
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
qtprojectorg pushed a commit that referenced this pull request Jul 22, 2023
Says ASAN:

    Direct leak of 524 byte(s) in 1 object(s) allocated from:
    #0 0x7f708f0a67cf in __interceptor_malloc ../../../../gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x7f707d94bf9e in CRYPTO_malloc crypto/mem.c:196
    #2 0x7f707d7bd248 in asn1_item_flags_i2d crypto/asn1/tasn_enc.c:65
    #3 0x7f707d7bd1b7 in ASN1_item_i2d crypto/asn1/tasn_enc.c:45
    #4 0x7f707d85b7be in i2d_DHparams crypto/dh/dh_asn1.c:54
    #5 0x7f7075a82223 in q_i2d_DHparams(dh_st*, unsigned char**) qsslsocket_openssl_symbols.cpp:435
    #6 0x7f7075a82223 in QTlsBackendOpenSSL::dhParametersFromPem(QByteArray const&, QByteArray*) const qssldiffiehellmanparameters_openssl.cpp:139
    #7 0x7f708ca9b588 in QSslDiffieHellmanParametersPrivate::initFromPem(QByteArray const&) qssldiffiehellmanparameters.cpp:285
    #8 0x7f708ca9b588 in QSslDiffieHellmanParameters::fromEncoded(QByteArray const&, QSsl::EncodingFormat) qssldiffiehellmanparameters.cpp:94
    #9 0x55fd8a545ebe in tst_QSslDiffieHellmanParameters::constructionPEM() tst_qssldiffiehellmanparameters.cpp:98
    [...]

The pointer returned in the out-parameter of a i2d_DHparams() call is
supposed to be OPENSSL_free()ed by the user (this is not at all
obvious from the docs¹, but an SO answer² indicates that's how it
should be (as well as asan stopping from complaining with this
patch applied)).

¹ https://www.openssl.org/docs/man3.1/man3/i2d_DHparams.html
² https://stackoverflow.com/a/53563669.

Amends 2cf63c7.

[ChangeLog][QtNetwork][SSL] Fixed a memory leak in parsing of
PEM-encoded Diffie-Hellman parameters.

Change-Id: I9ed4a26c4676db1c0d54a1945a4fb5014ce568cd
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
(cherry picked from commit 676087e)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Martchus pushed a commit to Martchus/qtbase that referenced this pull request Aug 12, 2023
Says ASAN:

    Direct leak of 524 byte(s) in 1 object(s) allocated from:
    #0 0x7f708f0a67cf in __interceptor_malloc ../../../../gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
    qt#1 0x7f707d94bf9e in CRYPTO_malloc crypto/mem.c:196
    qt#2 0x7f707d7bd248 in asn1_item_flags_i2d crypto/asn1/tasn_enc.c:65
    qt#3 0x7f707d7bd1b7 in ASN1_item_i2d crypto/asn1/tasn_enc.c:45
    qt#4 0x7f707d85b7be in i2d_DHparams crypto/dh/dh_asn1.c:54
    qt#5 0x7f7075a82223 in q_i2d_DHparams(dh_st*, unsigned char**) qsslsocket_openssl_symbols.cpp:435
    qt#6 0x7f7075a82223 in QTlsBackendOpenSSL::dhParametersFromPem(QByteArray const&, QByteArray*) const qssldiffiehellmanparameters_openssl.cpp:139
    qt#7 0x7f708ca9b588 in QSslDiffieHellmanParametersPrivate::initFromPem(QByteArray const&) qssldiffiehellmanparameters.cpp:285
    qt#8 0x7f708ca9b588 in QSslDiffieHellmanParameters::fromEncoded(QByteArray const&, QSsl::EncodingFormat) qssldiffiehellmanparameters.cpp:94
    qt#9 0x55fd8a545ebe in tst_QSslDiffieHellmanParameters::constructionPEM() tst_qssldiffiehellmanparameters.cpp:98
    [...]

The pointer returned in the out-parameter of a i2d_DHparams() call is
supposed to be OPENSSL_free()ed by the user (this is not at all
obvious from the docs¹, but an SO answer² indicates that's how it
should be (as well as asan stopping from complaining with this
patch applied)).

¹ https://www.openssl.org/docs/man3.1/man3/i2d_DHparams.html
² https://stackoverflow.com/a/53563669.

Amends 2cf63c7.

[ChangeLog][QtNetwork][SSL] Fixed a memory leak in parsing of
PEM-encoded Diffie-Hellman parameters.

Pick-to: 6.6 6.5 6.2 5.15
Change-Id: I9ed4a26c4676db1c0d54a1945a4fb5014ce568cd
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
(cherry picked from commit 676087e)
qtprojectorg pushed a commit that referenced this pull request Sep 6, 2023
This reverts commit f20adcd. The
implementation had the right idea, but this is not expected to work
reliably in C++. It's jumping out of several frames without cleaning
them out properly and our ASan-based memory leak-checker has started
complaining (the next commit will move this test elsewhere).

   ==19313==ERROR: LeakSanitizer: detected memory leaks

 Direct leak of 258 byte(s) in 1 object(s) allocated from:
       #0 0x7ffa505c8e48 in __interceptor_malloc (/usr/lib64/libasan.so.5+0x109e48)
       #1 0x7ffa4f2d7ff9  (/home/qt/work/install/lib/libQt6Core.so.6+0x896ff9)
       #2 0x7ffa4f2d834d in QArrayData::allocate(QArrayData**, long long, long long, long long, QArrayData::AllocationOption) (/home/qt/work/install/lib/libQt6Core.so.6+0x89734d)
       #3 0x7ffa4f23b700  (/home/qt/work/install/lib/libQt6Core.so.6+0x7fa700)
       #4 0x7ffa4f1f6cc8 in QString::reallocData(long long, QArrayData::AllocationOption) (/home/qt/work/install/lib/libQt6Core.so.6+0x7b5cc8)
       #5 0x7ffa4f1f68a7 in QString::resize(long long) (/home/qt/work/install/lib/libQt6Core.so.6+0x7b58a7)
       #6 0x7ffa4f2092ff  (/home/qt/work/install/lib/libQt6Core.so.6+0x7c82ff)
       #7 0x7ffa4f209e09 in QString::vasprintf(char const*, __va_list_tag*) (/home/qt/work/install/lib/libQt6Core.so.6+0x7c8e09)
       #8 0x7ffa4ed0d83d  (/home/qt/work/install/lib/libQt6Core.so.6+0x2cc83d)
       #9 0x7ffa4ed114a9 in QMessageLogger::fatal(char const*, ...) const (/home/qt/work/install/lib/libQt6Core.so.6+0x2d04a9)
       #10 0x5641d2604c40 in tst_Silent::messages() /home/qt/work/qt/qtbase/tests/auto/testlib/selftests/silent/tst_silent.cpp:77
       #11 0x5641d26050fb in tst_Silent::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) tests/auto/testlib/selftests/silent/silent_autogen/include/tst_silent.moc:118

The restoration of the signal handler (which QtTest now has) is also
wrong: this needed to use sigaction() instead.

Change-Id: Ifa1111900d6945ea8e05fffd177f14fbc09a1d7d
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Martchus pushed a commit to Martchus/qtbase that referenced this pull request Oct 8, 2023
Says ASAN:

    Direct leak of 524 byte(s) in 1 object(s) allocated from:
    #0 0x7f708f0a67cf in __interceptor_malloc ../../../../gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
    qt#1 0x7f707d94bf9e in CRYPTO_malloc crypto/mem.c:196
    qt#2 0x7f707d7bd248 in asn1_item_flags_i2d crypto/asn1/tasn_enc.c:65
    qt#3 0x7f707d7bd1b7 in ASN1_item_i2d crypto/asn1/tasn_enc.c:45
    qt#4 0x7f707d85b7be in i2d_DHparams crypto/dh/dh_asn1.c:54
    qt#5 0x7f7075a82223 in q_i2d_DHparams(dh_st*, unsigned char**) qsslsocket_openssl_symbols.cpp:435
    qt#6 0x7f7075a82223 in QTlsBackendOpenSSL::dhParametersFromPem(QByteArray const&, QByteArray*) const qssldiffiehellmanparameters_openssl.cpp:139
    qt#7 0x7f708ca9b588 in QSslDiffieHellmanParametersPrivate::initFromPem(QByteArray const&) qssldiffiehellmanparameters.cpp:285
    qt#8 0x7f708ca9b588 in QSslDiffieHellmanParameters::fromEncoded(QByteArray const&, QSsl::EncodingFormat) qssldiffiehellmanparameters.cpp:94
    qt#9 0x55fd8a545ebe in tst_QSslDiffieHellmanParameters::constructionPEM() tst_qssldiffiehellmanparameters.cpp:98
    [...]

The pointer returned in the out-parameter of a i2d_DHparams() call is
supposed to be OPENSSL_free()ed by the user (this is not at all
obvious from the docs¹, but an SO answer² indicates that's how it
should be (as well as asan stopping from complaining with this
patch applied)).

¹ https://www.openssl.org/docs/man3.1/man3/i2d_DHparams.html
² https://stackoverflow.com/a/53563669.

Amends 2cf63c7.

[ChangeLog][QtNetwork][SSL] Fixed a memory leak in parsing of
PEM-encoded Diffie-Hellman parameters.

Pick-to: 6.6 6.5 6.2 5.15
Change-Id: I9ed4a26c4676db1c0d54a1945a4fb5014ce568cd
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
(cherry picked from commit 676087e)
Martchus pushed a commit to Martchus/qtbase that referenced this pull request Jan 7, 2024
Says ASAN:

    Direct leak of 524 byte(s) in 1 object(s) allocated from:
    #0 0x7f708f0a67cf in __interceptor_malloc ../../../../gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
    qt#1 0x7f707d94bf9e in CRYPTO_malloc crypto/mem.c:196
    qt#2 0x7f707d7bd248 in asn1_item_flags_i2d crypto/asn1/tasn_enc.c:65
    qt#3 0x7f707d7bd1b7 in ASN1_item_i2d crypto/asn1/tasn_enc.c:45
    qt#4 0x7f707d85b7be in i2d_DHparams crypto/dh/dh_asn1.c:54
    qt#5 0x7f7075a82223 in q_i2d_DHparams(dh_st*, unsigned char**) qsslsocket_openssl_symbols.cpp:435
    qt#6 0x7f7075a82223 in QTlsBackendOpenSSL::dhParametersFromPem(QByteArray const&, QByteArray*) const qssldiffiehellmanparameters_openssl.cpp:139
    qt#7 0x7f708ca9b588 in QSslDiffieHellmanParametersPrivate::initFromPem(QByteArray const&) qssldiffiehellmanparameters.cpp:285
    qt#8 0x7f708ca9b588 in QSslDiffieHellmanParameters::fromEncoded(QByteArray const&, QSsl::EncodingFormat) qssldiffiehellmanparameters.cpp:94
    qt#9 0x55fd8a545ebe in tst_QSslDiffieHellmanParameters::constructionPEM() tst_qssldiffiehellmanparameters.cpp:98
    [...]

The pointer returned in the out-parameter of a i2d_DHparams() call is
supposed to be OPENSSL_free()ed by the user (this is not at all
obvious from the docs¹, but an SO answer² indicates that's how it
should be (as well as asan stopping from complaining with this
patch applied)).

¹ https://www.openssl.org/docs/man3.1/man3/i2d_DHparams.html
² https://stackoverflow.com/a/53563669.

Amends 2cf63c7.

[ChangeLog][QtNetwork][SSL] Fixed a memory leak in parsing of
PEM-encoded Diffie-Hellman parameters.

Pick-to: 6.6 6.5 6.2 5.15
Change-Id: I9ed4a26c4676db1c0d54a1945a4fb5014ce568cd
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
(cherry picked from commit 676087e)
Martchus pushed a commit to Martchus/qtbase that referenced this pull request Mar 15, 2024
Says ASAN:

    Direct leak of 524 byte(s) in 1 object(s) allocated from:
    #0 0x7f708f0a67cf in __interceptor_malloc ../../../../gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
    qt#1 0x7f707d94bf9e in CRYPTO_malloc crypto/mem.c:196
    qt#2 0x7f707d7bd248 in asn1_item_flags_i2d crypto/asn1/tasn_enc.c:65
    qt#3 0x7f707d7bd1b7 in ASN1_item_i2d crypto/asn1/tasn_enc.c:45
    qt#4 0x7f707d85b7be in i2d_DHparams crypto/dh/dh_asn1.c:54
    qt#5 0x7f7075a82223 in q_i2d_DHparams(dh_st*, unsigned char**) qsslsocket_openssl_symbols.cpp:435
    qt#6 0x7f7075a82223 in QTlsBackendOpenSSL::dhParametersFromPem(QByteArray const&, QByteArray*) const qssldiffiehellmanparameters_openssl.cpp:139
    qt#7 0x7f708ca9b588 in QSslDiffieHellmanParametersPrivate::initFromPem(QByteArray const&) qssldiffiehellmanparameters.cpp:285
    qt#8 0x7f708ca9b588 in QSslDiffieHellmanParameters::fromEncoded(QByteArray const&, QSsl::EncodingFormat) qssldiffiehellmanparameters.cpp:94
    qt#9 0x55fd8a545ebe in tst_QSslDiffieHellmanParameters::constructionPEM() tst_qssldiffiehellmanparameters.cpp:98
    [...]

The pointer returned in the out-parameter of a i2d_DHparams() call is
supposed to be OPENSSL_free()ed by the user (this is not at all
obvious from the docs¹, but an SO answer² indicates that's how it
should be (as well as asan stopping from complaining with this
patch applied)).

¹ https://www.openssl.org/docs/man3.1/man3/i2d_DHparams.html
² https://stackoverflow.com/a/53563669.

Amends 2cf63c7.

[ChangeLog][QtNetwork][SSL] Fixed a memory leak in parsing of
PEM-encoded Diffie-Hellman parameters.

Pick-to: 6.6 6.5 6.2 5.15
Change-Id: I9ed4a26c4676db1c0d54a1945a4fb5014ce568cd
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
(cherry picked from commit 676087e)
Martchus pushed a commit to Martchus/qtbase that referenced this pull request May 28, 2024
Says ASAN:

    Direct leak of 524 byte(s) in 1 object(s) allocated from:
    #0 0x7f708f0a67cf in __interceptor_malloc ../../../../gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
    qt#1 0x7f707d94bf9e in CRYPTO_malloc crypto/mem.c:196
    qt#2 0x7f707d7bd248 in asn1_item_flags_i2d crypto/asn1/tasn_enc.c:65
    qt#3 0x7f707d7bd1b7 in ASN1_item_i2d crypto/asn1/tasn_enc.c:45
    qt#4 0x7f707d85b7be in i2d_DHparams crypto/dh/dh_asn1.c:54
    qt#5 0x7f7075a82223 in q_i2d_DHparams(dh_st*, unsigned char**) qsslsocket_openssl_symbols.cpp:435
    qt#6 0x7f7075a82223 in QTlsBackendOpenSSL::dhParametersFromPem(QByteArray const&, QByteArray*) const qssldiffiehellmanparameters_openssl.cpp:139
    qt#7 0x7f708ca9b588 in QSslDiffieHellmanParametersPrivate::initFromPem(QByteArray const&) qssldiffiehellmanparameters.cpp:285
    qt#8 0x7f708ca9b588 in QSslDiffieHellmanParameters::fromEncoded(QByteArray const&, QSsl::EncodingFormat) qssldiffiehellmanparameters.cpp:94
    qt#9 0x55fd8a545ebe in tst_QSslDiffieHellmanParameters::constructionPEM() tst_qssldiffiehellmanparameters.cpp:98
    [...]

The pointer returned in the out-parameter of a i2d_DHparams() call is
supposed to be OPENSSL_free()ed by the user (this is not at all
obvious from the docs¹, but an SO answer² indicates that's how it
should be (as well as asan stopping from complaining with this
patch applied)).

¹ https://www.openssl.org/docs/man3.1/man3/i2d_DHparams.html
² https://stackoverflow.com/a/53563669.

Amends 2cf63c7.

[ChangeLog][QtNetwork][SSL] Fixed a memory leak in parsing of
PEM-encoded Diffie-Hellman parameters.

Pick-to: 6.6 6.5 6.2 5.15
Change-Id: I9ed4a26c4676db1c0d54a1945a4fb5014ce568cd
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
(cherry picked from commit 676087e)
qtprojectorg pushed a commit that referenced this pull request Aug 30, 2024
Says ASAN:

    Direct leak of 524 byte(s) in 1 object(s) allocated from:
    #0 0x7f708f0a67cf in __interceptor_malloc ../../../../gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x7f707d94bf9e in CRYPTO_malloc crypto/mem.c:196
    #2 0x7f707d7bd248 in asn1_item_flags_i2d crypto/asn1/tasn_enc.c:65
    #3 0x7f707d7bd1b7 in ASN1_item_i2d crypto/asn1/tasn_enc.c:45
    #4 0x7f707d85b7be in i2d_DHparams crypto/dh/dh_asn1.c:54
    #5 0x7f7075a82223 in q_i2d_DHparams(dh_st*, unsigned char**) qsslsocket_openssl_symbols.cpp:435
    #6 0x7f7075a82223 in QTlsBackendOpenSSL::dhParametersFromPem(QByteArray const&, QByteArray*) const qssldiffiehellmanparameters_openssl.cpp:139
    #7 0x7f708ca9b588 in QSslDiffieHellmanParametersPrivate::initFromPem(QByteArray const&) qssldiffiehellmanparameters.cpp:285
    #8 0x7f708ca9b588 in QSslDiffieHellmanParameters::fromEncoded(QByteArray const&, QSsl::EncodingFormat) qssldiffiehellmanparameters.cpp:94
    #9 0x55fd8a545ebe in tst_QSslDiffieHellmanParameters::constructionPEM() tst_qssldiffiehellmanparameters.cpp:98
    [...]

The pointer returned in the out-parameter of a i2d_DHparams() call is
supposed to be OPENSSL_free()ed by the user (this is not at all
obvious from the docs¹, but an SO answer² indicates that's how it
should be (as well as asan stopping from complaining with this
patch applied)).

¹ https://www.openssl.org/docs/man3.1/man3/i2d_DHparams.html
² https://stackoverflow.com/a/53563669.

Amends 2cf63c7.

[ChangeLog][QtNetwork][SSL] Fixed a memory leak in parsing of
PEM-encoded Diffie-Hellman parameters.

Change-Id: I9ed4a26c4676db1c0d54a1945a4fb5014ce568cd
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
(cherry picked from commit 676087e)
qtprojectorg pushed a commit that referenced this pull request Oct 9, 2024
Says ASAN:

    Direct leak of 524 byte(s) in 1 object(s) allocated from:
    #0 0x7f708f0a67cf in __interceptor_malloc ../../../../gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x7f707d94bf9e in CRYPTO_malloc crypto/mem.c:196
    #2 0x7f707d7bd248 in asn1_item_flags_i2d crypto/asn1/tasn_enc.c:65
    #3 0x7f707d7bd1b7 in ASN1_item_i2d crypto/asn1/tasn_enc.c:45
    #4 0x7f707d85b7be in i2d_DHparams crypto/dh/dh_asn1.c:54
    #5 0x7f7075a82223 in q_i2d_DHparams(dh_st*, unsigned char**) qsslsocket_openssl_symbols.cpp:435
    #6 0x7f7075a82223 in QTlsBackendOpenSSL::dhParametersFromPem(QByteArray const&, QByteArray*) const qssldiffiehellmanparameters_openssl.cpp:139
    #7 0x7f708ca9b588 in QSslDiffieHellmanParametersPrivate::initFromPem(QByteArray const&) qssldiffiehellmanparameters.cpp:285
    #8 0x7f708ca9b588 in QSslDiffieHellmanParameters::fromEncoded(QByteArray const&, QSsl::EncodingFormat) qssldiffiehellmanparameters.cpp:94
    #9 0x55fd8a545ebe in tst_QSslDiffieHellmanParameters::constructionPEM() tst_qssldiffiehellmanparameters.cpp:98
    [...]

The pointer returned in the out-parameter of a i2d_DHparams() call is
supposed to be OPENSSL_free()ed by the user (this is not at all
obvious from the docs¹, but an SO answer² indicates that's how it
should be (as well as asan stopping from complaining with this
patch applied)).

¹ https://www.openssl.org/docs/man3.1/man3/i2d_DHparams.html
² https://stackoverflow.com/a/53563669.

Amends 2cf63c7.

[ChangeLog][QtNetwork][SSL] Fixed a memory leak in parsing of
PEM-encoded Diffie-Hellman parameters.

Change-Id: I9ed4a26c4676db1c0d54a1945a4fb5014ce568cd
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
(cherry picked from commit 676087e)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
qtprojectorg pushed a commit that referenced this pull request Apr 2, 2025
QLineEdit remembers whether a QWidget size-widget came from a
QWidgetAction or is just one of its own QLineEditIconButtons. On
removal of the action, if QWidgetAction, it will ask the action to
deal with its widget, calling QWidgetAction::releaseWidget(),
otherwise it just deletes the QLineEditIconButton itself.

This is fine if the action is being removed from the line edit, but
not immediately deleted. But if the action is being deleted while its
widget is still in a QLineEdit, then the QLineEdit is informed of this
only by ~QAction(), at which point the QWidgetAction has ceased to
exist and the cast, in QLineEditPrivate::removeAction(), to
QWidgetAction is UB.

Says UBSan:

  qlineedit_p.cpp:656:10: runtime error: downcast of address 0x6020000c3950 which does not point to an object of type 'QWidgetAction'
   0x6020000c3950: note: object is of type 'QAction'
    00 00 00 00  70 57 49 81 3d 7f 00 00  80 bc 0c 00 50 61 00 00  03 02 00 00 10 00 00 00  a6 01 00 71
                 ^~~~~~~~~~~~~~~~~~~~~~~
                 vptr for 'QAction'
    #0 0x7f3d93910686 in QLineEditPrivate::removeAction(QAction*) qlineedit_p.cpp:656
    #1 0x7f3d938b44bc in QLineEdit::event(QEvent*) qlineedit.cpp:1469
    #2 0x7f3d91c50211 in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3309
    #3 0x7f3d91cd160a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259
    #4 0x7f3d697f6ada in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111
    #5 0x7f3d697f94e3 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.cpp:1551
    #6 0x7f3d92345199 in QWidget::removeAction(QAction*) qwidget.cpp:3215
    #7 0x7f3d92e47202 in QtWidgetsActionPrivate::destroy() qaction_widgets.cpp:35
    #8 0x7f3d7f75d5fb in QAction::~QAction() qaction.cpp:451
    #9 0x7f3d92e4cc76 in QWidgetAction::~QWidgetAction() qwidgetaction.cpp:94
    #10 0x7f3d92e4e965 in QWidgetAction::~QWidgetAction() qwidgetaction.cpp:94
    #11 0x558c993da3b0 in tst_QLineEdit::sideWidgets() tst_qlineedit.cpp:4693

To fix, check the dynamic type of the action (using qobject_cast)
before calling QWidgetAction::releaseWidget(). If the cast fails, the
QWidgetAction will have dealt with the widget itself, in its own dtor,
so QLineEdit needn't do anything.

Unfortunately, fixing this centrally by just dragging destroy() down
from ~QAction() to ~QWidgetAction() causes use-after-free in other
test functions of tst_QLineEdit, so I deciced to fix this at the
QLineEdit level only.

Amends 9ce12cc.

Pick-to: 6.9 6.8 6.5 5.15
Change-Id: I3c514dbd1f1a4e1510df3dd9ac67b4bab50e63e9
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
qtprojectorg pushed a commit that referenced this pull request Apr 3, 2025
QLineEdit remembers whether a QWidget size-widget came from a
QWidgetAction or is just one of its own QLineEditIconButtons. On
removal of the action, if QWidgetAction, it will ask the action to
deal with its widget, calling QWidgetAction::releaseWidget(),
otherwise it just deletes the QLineEditIconButton itself.

This is fine if the action is being removed from the line edit, but
not immediately deleted. But if the action is being deleted while its
widget is still in a QLineEdit, then the QLineEdit is informed of this
only by ~QAction(), at which point the QWidgetAction has ceased to
exist and the cast, in QLineEditPrivate::removeAction(), to
QWidgetAction is UB.

Says UBSan:

  qlineedit_p.cpp:656:10: runtime error: downcast of address 0x6020000c3950 which does not point to an object of type 'QWidgetAction'
   0x6020000c3950: note: object is of type 'QAction'
    00 00 00 00  70 57 49 81 3d 7f 00 00  80 bc 0c 00 50 61 00 00  03 02 00 00 10 00 00 00  a6 01 00 71
                 ^~~~~~~~~~~~~~~~~~~~~~~
                 vptr for 'QAction'
    #0 0x7f3d93910686 in QLineEditPrivate::removeAction(QAction*) qlineedit_p.cpp:656
    #1 0x7f3d938b44bc in QLineEdit::event(QEvent*) qlineedit.cpp:1469
    #2 0x7f3d91c50211 in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3309
    #3 0x7f3d91cd160a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259
    #4 0x7f3d697f6ada in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111
    #5 0x7f3d697f94e3 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.cpp:1551
    #6 0x7f3d92345199 in QWidget::removeAction(QAction*) qwidget.cpp:3215
    #7 0x7f3d92e47202 in QtWidgetsActionPrivate::destroy() qaction_widgets.cpp:35
    #8 0x7f3d7f75d5fb in QAction::~QAction() qaction.cpp:451
    #9 0x7f3d92e4cc76 in QWidgetAction::~QWidgetAction() qwidgetaction.cpp:94
    #10 0x7f3d92e4e965 in QWidgetAction::~QWidgetAction() qwidgetaction.cpp:94
    #11 0x558c993da3b0 in tst_QLineEdit::sideWidgets() tst_qlineedit.cpp:4693

To fix, check the dynamic type of the action (using qobject_cast)
before calling QWidgetAction::releaseWidget(). If the cast fails, the
QWidgetAction will have dealt with the widget itself, in its own dtor,
so QLineEdit needn't do anything.

Unfortunately, fixing this centrally by just dragging destroy() down
from ~QAction() to ~QWidgetAction() causes use-after-free in other
test functions of tst_QLineEdit, so I deciced to fix this at the
QLineEdit level only.

Amends 9ce12cc.

Pick-to: 6.8 6.5 5.15
Change-Id: I3c514dbd1f1a4e1510df3dd9ac67b4bab50e63e9
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
(cherry picked from commit bf62a97)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
qtprojectorg pushed a commit that referenced this pull request Apr 3, 2025
QLineEdit remembers whether a QWidget size-widget came from a
QWidgetAction or is just one of its own QLineEditIconButtons. On
removal of the action, if QWidgetAction, it will ask the action to
deal with its widget, calling QWidgetAction::releaseWidget(),
otherwise it just deletes the QLineEditIconButton itself.

This is fine if the action is being removed from the line edit, but
not immediately deleted. But if the action is being deleted while its
widget is still in a QLineEdit, then the QLineEdit is informed of this
only by ~QAction(), at which point the QWidgetAction has ceased to
exist and the cast, in QLineEditPrivate::removeAction(), to
QWidgetAction is UB.

Says UBSan:

  qlineedit_p.cpp:656:10: runtime error: downcast of address 0x6020000c3950 which does not point to an object of type 'QWidgetAction'
   0x6020000c3950: note: object is of type 'QAction'
    00 00 00 00  70 57 49 81 3d 7f 00 00  80 bc 0c 00 50 61 00 00  03 02 00 00 10 00 00 00  a6 01 00 71
                 ^~~~~~~~~~~~~~~~~~~~~~~
                 vptr for 'QAction'
    #0 0x7f3d93910686 in QLineEditPrivate::removeAction(QAction*) qlineedit_p.cpp:656
    #1 0x7f3d938b44bc in QLineEdit::event(QEvent*) qlineedit.cpp:1469
    #2 0x7f3d91c50211 in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3309
    #3 0x7f3d91cd160a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259
    #4 0x7f3d697f6ada in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111
    #5 0x7f3d697f94e3 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.cpp:1551
    #6 0x7f3d92345199 in QWidget::removeAction(QAction*) qwidget.cpp:3215
    #7 0x7f3d92e47202 in QtWidgetsActionPrivate::destroy() qaction_widgets.cpp:35
    #8 0x7f3d7f75d5fb in QAction::~QAction() qaction.cpp:451
    #9 0x7f3d92e4cc76 in QWidgetAction::~QWidgetAction() qwidgetaction.cpp:94
    #10 0x7f3d92e4e965 in QWidgetAction::~QWidgetAction() qwidgetaction.cpp:94
    #11 0x558c993da3b0 in tst_QLineEdit::sideWidgets() tst_qlineedit.cpp:4693

To fix, check the dynamic type of the action (using qobject_cast)
before calling QWidgetAction::releaseWidget(). If the cast fails, the
QWidgetAction will have dealt with the widget itself, in its own dtor,
so QLineEdit needn't do anything.

Unfortunately, fixing this centrally by just dragging destroy() down
from ~QAction() to ~QWidgetAction() causes use-after-free in other
test functions of tst_QLineEdit, so I deciced to fix this at the
QLineEdit level only.

Amends 9ce12cc.

Pick-to: 6.5 5.15
Change-Id: I3c514dbd1f1a4e1510df3dd9ac67b4bab50e63e9
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
(cherry picked from commit bf62a97)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 82cf1c0)
qtprojectorg pushed a commit that referenced this pull request Apr 3, 2025
Amends b6b489d, which introduced UB
(invalid downcast):

By the time the
QMainWindowTabBars are destroyed, and they want to unregister
themselves from the QMainWindow, the ex-QMainWindow has already been
demoted to a QWidget. Says UBSan:

  qmainwindow.cpp:63:47: runtime error: member call on address 0x6040000267d0 which does not point to an object of type 'QMainWindow'
  0x6040000267d0: note: object is of type 'QWidget'
   00 00 00 00  28 c1 e6 f3 c7 7f 00 00  80 24 00 00 60 61 00 00  d8 c2 e6 f3 c7 7f 00 00  00 00 be be
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QWidget'
    #0 0x7fc7f06da8c5 in QMainWindowPrivate::mainWindowLayout(QMainWindow const*) qmainwindow.cpp:63
    #1 0x7fc7f06da8c5 in qt_mainwindow_layout(QMainWindow const*) qmainwindow.cpp:69
    #2 0x7fc7f07bb4ed in QMainWindowTabBar::~QMainWindowTabBar() qmainwindowlayout.cpp:2042
    #3 0x7fc7f07bf4e5 in QMainWindowTabBar::~QMainWindowTabBar() qmainwindowlayout.cpp:2047
    #4 0x7fc7c69f9c2a in QObjectPrivate::deleteChildren() qobject.cpp:2226
    #5 0x7fc7ef0b7f3d in QWidget::~QWidget() qwidget.cpp:1557
    #6 0x7fc7f082c7c7 in QDockWidgetGroupWindow::~QDockWidgetGroupWindow() qmainwindowlayout_p.h:343
    #7 0x7fc7f082c7c7 in QDockWidgetGroupWindow::~QDockWidgetGroupWindow() qmainwindowlayout_p.h:343
    #8 0x7fc7c69f9c2a in QObjectPrivate::deleteChildren() qobject.cpp:2226
    #9 0x7fc7ef0b7f3d in QWidget::~QWidget() qwidget.cpp:1557
    #10 0x7fc7f06ce495 in QMainWindow::~QMainWindow() qmainwindow.cpp:338
    #12 0x556a6180a84c in std::default_delete<QMainWindow>::operator()(QMainWindow*) const unique_ptr.h:85
    #13 0x556a6180a84c in std::unique_ptr<QMainWindow, std::default_delete<QMainWindow> >::~unique_ptr() unique_ptr.h:361
    #14 0x556a6180a84c in tst_QDockWidget::setFloatingReparenting() tst_qdockwidget.cpp:492

Use qobject_cast to verify that the mainWindow is not pointing to a
QMainWindow that is being destroyed (and has passed the ~QMainWindow
destructor). If the main window is destroyed, then removing the tab bar
from the list of unused tab bars is unnecessary.

Pick-to: 6.9 6.8 6.5
Change-Id: I25e12d79198137b75cd2576ff1440b6c94277eba
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
qtprojectorg pushed a commit that referenced this pull request Apr 3, 2025
Amends b6b489d, which introduced UB
(invalid downcast):

By the time the
QMainWindowTabBars are destroyed, and they want to unregister
themselves from the QMainWindow, the ex-QMainWindow has already been
demoted to a QWidget. Says UBSan:

  qmainwindow.cpp:63:47: runtime error: member call on address 0x6040000267d0 which does not point to an object of type 'QMainWindow'
  0x6040000267d0: note: object is of type 'QWidget'
   00 00 00 00  28 c1 e6 f3 c7 7f 00 00  80 24 00 00 60 61 00 00  d8 c2 e6 f3 c7 7f 00 00  00 00 be be
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QWidget'
    #0 0x7fc7f06da8c5 in QMainWindowPrivate::mainWindowLayout(QMainWindow const*) qmainwindow.cpp:63
    #1 0x7fc7f06da8c5 in qt_mainwindow_layout(QMainWindow const*) qmainwindow.cpp:69
    #2 0x7fc7f07bb4ed in QMainWindowTabBar::~QMainWindowTabBar() qmainwindowlayout.cpp:2042
    #3 0x7fc7f07bf4e5 in QMainWindowTabBar::~QMainWindowTabBar() qmainwindowlayout.cpp:2047
    #4 0x7fc7c69f9c2a in QObjectPrivate::deleteChildren() qobject.cpp:2226
    #5 0x7fc7ef0b7f3d in QWidget::~QWidget() qwidget.cpp:1557
    #6 0x7fc7f082c7c7 in QDockWidgetGroupWindow::~QDockWidgetGroupWindow() qmainwindowlayout_p.h:343
    #7 0x7fc7f082c7c7 in QDockWidgetGroupWindow::~QDockWidgetGroupWindow() qmainwindowlayout_p.h:343
    #8 0x7fc7c69f9c2a in QObjectPrivate::deleteChildren() qobject.cpp:2226
    #9 0x7fc7ef0b7f3d in QWidget::~QWidget() qwidget.cpp:1557
    #10 0x7fc7f06ce495 in QMainWindow::~QMainWindow() qmainwindow.cpp:338
    #12 0x556a6180a84c in std::default_delete<QMainWindow>::operator()(QMainWindow*) const unique_ptr.h:85
    #13 0x556a6180a84c in std::unique_ptr<QMainWindow, std::default_delete<QMainWindow> >::~unique_ptr() unique_ptr.h:361
    #14 0x556a6180a84c in tst_QDockWidget::setFloatingReparenting() tst_qdockwidget.cpp:492

Use qobject_cast to verify that the mainWindow is not pointing to a
QMainWindow that is being destroyed (and has passed the ~QMainWindow
destructor). If the main window is destroyed, then removing the tab bar
from the list of unused tab bars is unnecessary.

Pick-to: 6.8 6.5
Change-Id: I25e12d79198137b75cd2576ff1440b6c94277eba
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
(cherry picked from commit 1bbbacb)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
qtprojectorg pushed a commit that referenced this pull request Apr 4, 2025
The process by which the QDockAreaLayout changes a QDockAreaLayoutInfo
from representing a QWidget that's being deleted to representing a
QPlaceholderItem involves the construction of the latter from the
former. If a QDockWidget is being deleted, however, at the time the
QDockAreaLayout notices, the ex-QDockWidget has been demoted to a
QObject, causing the calls to QWidget member functions to be UB:

Says UBSan:

  qdockarealayout.cpp:46:25: runtime error: member call on address 0x7ffe74a429d0 which does not point to an object of type 'QWidget'
  0x7ffe74a429d0: note: object is of type 'QObject'
   33 7f 00 00  c0 ea 73 6e 33 7f 00 00  00 12 00 00 70 61 00 00  40 cd 41 83 33 7f 00 00  00 00 00 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QObject'
    #0 0x7f339546e251 in QPlaceHolderItem::QPlaceHolderItem(QWidget*) qdockarealayout.cpp:46
    #1 0x7f33955169a8 in QDockAreaLayoutInfo::takeAt(int*, int) qdockarealayout.cpp:1780
    #2 0x7f3395517175 in QDockAreaLayout::takeAt(int*, int) qdockarealayout.cpp:3432
    #3 0x7f33959e38a8 in QMainWindowLayoutState::takeAt(int, int*) qmainwindowlayout.cpp:927
    #4 0x7f33959e38a8 in QMainWindowLayoutState::takeAt(int, int*) qmainwindowlayout.cpp:919
    #5 0x7f3395a42cdd in QMainWindowLayout::takeAt(int) qmainwindowlayout.cpp:2238
    #6 0x7f3393fae246 in removeWidgetRecursively qlayout.cpp:485
    #7 0x7f3393fb8300 in QLayout::widgetEvent(QEvent*) qlayout.cpp:544
    #8 0x7f3393bde28a in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3298
    #9 0x7f3393c5f74a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259
    #10 0x7f336b784ada in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111
    #11 0x7f336b7874e3 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.cpp:1551
    #12 0x7f336bcc624a in QObjectPrivate::setParent_helper(QObject*) qobject.cpp:2271
    #13 0x7f336bccd76c in QObject::~QObject() qobject.cpp:1146
    #14 0x7f339434e126 in QWidget::~QWidget() qwidget.cpp:1584
    #15 0x7f33955b5815 in QDockWidget::~QDockWidget() qdockwidget.cpp:1362
    [...]

  qwidget.h:816:25: runtime error: member call on address 0x7ffe74a429d0 which does not point to an object of type 'QWidget'
  0x7ffe74a429d0: note: object is of type 'QObject'
   33 7f 00 00  c0 ea 73 6e 33 7f 00 00  00 12 00 00 70 61 00 00  40 cd 41 83 33 7f 00 00  00 00 00 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QObject'
    #0 0x7f339546e0bb in QWidget::isWindow() const qwidget.h:816
    #1 0x7f339546e0bb in QPlaceHolderItem::QPlaceHolderItem(QWidget*) qdockarealayout.cpp:47
    [... rest as above...]

Fix by dragging the setParent(nullptr) up into ~QDockWidget().

Ordinarily, that call happens only in ~QObject(). But that's what
caused the layout to react to the ChildRemoved element too late. When
doing it here, the dock widget is still itself, and all the
QDockAreaLayout machinery can still access its QWidget-ness.

Amends the start of the public history.

After consulting with QtWidgets maintainer, not picking to 5.15,
since, even though slim, there's a non-zero chance this might break
something, somewhere.

Pick-to: 6.9 6.8 6.5
Change-Id: I5472bbb0fcab9fb74272a1da6c2a2896226e12bb
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
qtprojectorg pushed a commit that referenced this pull request Apr 4, 2025
…howAndHide()

The event filter was still active when the QDialogButtonBox in its
destruction process had already been demoted to QWidget. The
ignoreShowAndHide guard came too late, because by the time we check
it, in Private::handleButtonShowAndHide(), we had already cast q_ptr
to QDialogButtonBox.

Says UBSan:

  qdialogbuttonbox_p.h:26:5: runtime error: downcast of address 0x7fffefab47e0 which does not point to an object of type 'QDialogButtonBox'
  0x7fffefab47e0: note: object is of type 'QWidget'
   00 00 00 00  28 c1 5b 6e 6d 7f 00 00  80 22 10 00 90 61 00 00  d8 c2 5b 6e 6d 7f 00 00  00 00 00 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QWidget'
     #0 0x7f6d6b51141d in QDialogButtonBoxPrivate::q_func() qdialogbuttonbox_p.h:26
     #1 0x7f6d6b51141d in QDialogButtonBoxPrivate::handleButtonShowAndHide(QAbstractButton*, QEvent*) qdialogbuttonbox.cpp:913
     #2 0x7f6d6b51436c in eventFilter qdialogbuttonbox.cpp:127
     #3 0x7f6d40c1a8f1 in QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) qcoreapplication.cpp:1248
     #4 0x7f6d690b23d5 in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3303
     #5 0x7f6d69132a3a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259
     #6 0x7f6d40c1da6a in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111
     #7 0x7f6d40c20473 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.cpp:1551
     #8 0x7f6d690fe76c in QApplicationPrivate::setActiveWindow(QWidget*) qapplication.cpp:1857
     #9 0x7f6d695ac796 in QWidgetPrivate::deactivateWidgetCleanup() qwidget.cpp:2326
     #10 0x7f6d6976f8ce in QWidgetPrivate::hide_sys() qwidget.cpp:8256
     #11 0x7f6d69814579 in QWidgetPrivate::hide_helper() qwidget.cpp:8199
     #12 0x7f6d69887c1f in QWidgetPrivate::setVisible(bool) qwidget.cpp:8406
     #13 0x7f6d69775d23 in QWidget::setVisible(bool) qwidget.cpp:8314
     #14 0x7f6d695fb018 in QWidget::hide() qwidget.cpp:8179
     #15 0x7f6d6981a183 in QWidgetPrivate::handleClose(QWidgetPrivate::CloseMode) qwidget.cpp:8580
     #16 0x7f6d699e6fc6 in QWidgetWindow::closeEvent(QCloseEvent*) qwidgetwindow.cpp:871
     #17 0x7f6d52ef9f5d in QWindow::event(QEvent*) qwindow.cpp:2721
     #18 0x7f6d69a575f8 in QWidgetWindow::event(QEvent*) qwidgetwindow.cpp:398
     #19 0x7f6d690b2491 in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3309
     #20 0x7f6d69132a3a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259
     #21 0x7f6d40c1da6a in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111
     #22 0x7f6d40c205b3 in QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) qcoreapplication.cpp:1565
     #23 0x7f6d5287415b in QGuiApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent*) qguiapplication.cpp:2911
     #24 0x7f6d528b543f in QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) qguiapplication.cpp:2259
     #25 0x7f6d52fb5b02 in QWindowSystemEventHandler::sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) qwindowsysteminterface.cpp:190
     #26 0x7f6d52fb5b02 in bool QWindowSystemHelper<QWindowSystemInterface::SynchronousDelivery>::handleEvent<QWindowSystemInterfacePrivate::CloseEvent, QWindow*>(QWindow*) qwindowsysteminterface.cpp:102
     #27 0x7f6d52fb5b02 in handleWindowSystemEvent<QWindowSystemInterfacePrivate::CloseEvent, QWindowSystemInterface::SynchronousDelivery, QWindow*> qwindowsysteminterface.cpp:138
     #28 0x7f6d52fb5b02 in bool QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::SynchronousDelivery>(QWindow*) qwindowsysteminterface.cpp:351
     #29 0x7f6d52cb6f1e in QPlatformWindow::close() qplatformwindow.cpp:348
     #30 0x7f6d52e7e158 in QWindow::close() qwindow.cpp:2449
     #31 0x7f6d6981b4d2 in QWidgetPrivate::close() qwidget.cpp:8632
     #32 0x7f6d698205c6 in QWidget::~QWidget() qwidget.cpp:1508
     #33 0x7f6d6b4f6bf0 in QDialogButtonBox::~QDialogButtonBox() qdialogbuttonbox.cpp:496

To fix, don't delay the Q_Q to until after the ignoreShowAndHide
check, since that woould be brittle. Instead, do as we for signal/slot
connections, which we disconnect explicitly in ~QDialogButtonBox(),
and delete the EventFilter explicitly there, too. This way, it's more
natural, and also prevents all those useless event filter invocations
from having to be processed later on.

Amends aff0915. The original code,
using QDialogButtonBox::eventFilter(), was not affected, since by the
time QDialogButtonBox was demoted to QWidget, QWidget::eventFilter(),
not QDialogButtonBox::eventFilter() would been invoked. Which just
goes to show that one needs to be very careful with delegating too
much responsibilites to the Private class, as it lives, fully derived,
until ~QWidget() executes.

Pick-to: 6.9 6.8 6.5
Change-Id: I04f36fd6d7d160932bfe1494fdff464786b85047
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
qtprojectorg pushed a commit that referenced this pull request Apr 4, 2025
Amends b6b489d, which introduced UB
(invalid downcast):

By the time the
QMainWindowTabBars are destroyed, and they want to unregister
themselves from the QMainWindow, the ex-QMainWindow has already been
demoted to a QWidget. Says UBSan:

  qmainwindow.cpp:63:47: runtime error: member call on address 0x6040000267d0 which does not point to an object of type 'QMainWindow'
  0x6040000267d0: note: object is of type 'QWidget'
   00 00 00 00  28 c1 e6 f3 c7 7f 00 00  80 24 00 00 60 61 00 00  d8 c2 e6 f3 c7 7f 00 00  00 00 be be
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QWidget'
    #0 0x7fc7f06da8c5 in QMainWindowPrivate::mainWindowLayout(QMainWindow const*) qmainwindow.cpp:63
    #1 0x7fc7f06da8c5 in qt_mainwindow_layout(QMainWindow const*) qmainwindow.cpp:69
    #2 0x7fc7f07bb4ed in QMainWindowTabBar::~QMainWindowTabBar() qmainwindowlayout.cpp:2042
    #3 0x7fc7f07bf4e5 in QMainWindowTabBar::~QMainWindowTabBar() qmainwindowlayout.cpp:2047
    #4 0x7fc7c69f9c2a in QObjectPrivate::deleteChildren() qobject.cpp:2226
    #5 0x7fc7ef0b7f3d in QWidget::~QWidget() qwidget.cpp:1557
    #6 0x7fc7f082c7c7 in QDockWidgetGroupWindow::~QDockWidgetGroupWindow() qmainwindowlayout_p.h:343
    #7 0x7fc7f082c7c7 in QDockWidgetGroupWindow::~QDockWidgetGroupWindow() qmainwindowlayout_p.h:343
    #8 0x7fc7c69f9c2a in QObjectPrivate::deleteChildren() qobject.cpp:2226
    #9 0x7fc7ef0b7f3d in QWidget::~QWidget() qwidget.cpp:1557
    #10 0x7fc7f06ce495 in QMainWindow::~QMainWindow() qmainwindow.cpp:338
    #12 0x556a6180a84c in std::default_delete<QMainWindow>::operator()(QMainWindow*) const unique_ptr.h:85
    #13 0x556a6180a84c in std::unique_ptr<QMainWindow, std::default_delete<QMainWindow> >::~unique_ptr() unique_ptr.h:361
    #14 0x556a6180a84c in tst_QDockWidget::setFloatingReparenting() tst_qdockwidget.cpp:492

Use qobject_cast to verify that the mainWindow is not pointing to a
QMainWindow that is being destroyed (and has passed the ~QMainWindow
destructor). If the main window is destroyed, then removing the tab bar
from the list of unused tab bars is unnecessary.

Pick-to: 6.5
Change-Id: I25e12d79198137b75cd2576ff1440b6c94277eba
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
(cherry picked from commit 1bbbacb)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 19c4db4)
qtprojectorg pushed a commit that referenced this pull request Apr 10, 2025
…veButtonsFromMenuBar()

The function can be called from ~QMdiSubwindow(), and we checked for
QWidgetPrivate::data.in_destructor before proceeding with the removal
of buttons from the menubar, but we called
QPointer<QMdiSubwindow>::data()->window(), which, at this point in
time, had already been demoted to a QWidget:

Says UBSan:

  qpointer.h:75:14: runtime error: downcast of address 0x6040000aca10 which does not point to an object of type 'QMdiSubWindow'
   0x6040000aca10: note: object is of type 'QWidget'
    00 00 00 00  28 01 99 bc ff 7e 00 00  80 dc 0f 00 90 61 00 00  d8 02 99 bc ff 7e 00 00  00 00 be be
                 ^~~~~~~~~~~~~~~~~~~~~~~
                 vptr for 'QWidget'
       #0 0x7effb955f95a in QPointer<QMdiSubWindow>::data() const qpointer.h:75
       #1 0x7effb955f95a in QPointer<QMdiSubWindow>::operator->() const qpointer.h:79
       #2 0x7effb955f95a in QMdi::ControlContainer::removeButtonsFromMenuBar(QMenuBar*) qmdisubwindow.cpp:795
       #3 0x7effb9563031 in QMdi::ControlContainer::~ControlContainer() qmdisubwindow.cpp:717
       #4 0x7effb9566595 in QMdi::ControlContainer::~ControlContainer() qmdisubwindow.cpp:723
       #5 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #6 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #7 0x7effb95cc02c in QMdiSubWindow::~QMdiSubWindow() qmdisubwindow.cpp:2254
       #8 0x7effb95cc1d5 in QMdiSubWindow::~QMdiSubWindow() qmdisubwindow.cpp:2254
       #9 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #10 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #11 0x7effb7bffba5 in QWidget::~QWidget() qwidget.cpp:1584
       #12 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #13 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #14 0x7effb85f0dc5 in QFrame::~QFrame() qframe.cpp:235
       #15 0x7effb859c747 in QAbstractScrollArea::~QAbstractScrollArea() qabstractscrollarea.cpp:478
       #16 0x7effb93c08a6 in QMdiArea::~QMdiArea() qmdiarea.cpp:1703
       #17 0x7effb93c0e55 in QMdiArea::~QMdiArea() qmdiarea.cpp:1703
       #18 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #19 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #20 0x7effb920a425 in QMainWindow::~QMainWindow() qmainwindow.cpp:338

Fix by deleting the ControlContainer already from ~QMdiSubwindow(),
ie. when we have not yet been demoted to QWidget.

Amends the start of the public history.

Pick-to: 6.9 6.8 6.5 5.15
Change-Id: Ia43c857bc1842b2b4957cc79e00f790b045d8f94
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
qtprojectorg pushed a commit that referenced this pull request Apr 12, 2025
…howAndHide()

The event filter was still active when the QDialogButtonBox in its
destruction process had already been demoted to QWidget. The
ignoreShowAndHide guard came too late, because by the time we check
it, in Private::handleButtonShowAndHide(), we had already cast q_ptr
to QDialogButtonBox.

Says UBSan:

  qdialogbuttonbox_p.h:26:5: runtime error: downcast of address 0x7fffefab47e0 which does not point to an object of type 'QDialogButtonBox'
  0x7fffefab47e0: note: object is of type 'QWidget'
   00 00 00 00  28 c1 5b 6e 6d 7f 00 00  80 22 10 00 90 61 00 00  d8 c2 5b 6e 6d 7f 00 00  00 00 00 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QWidget'
     #0 0x7f6d6b51141d in QDialogButtonBoxPrivate::q_func() qdialogbuttonbox_p.h:26
     #1 0x7f6d6b51141d in QDialogButtonBoxPrivate::handleButtonShowAndHide(QAbstractButton*, QEvent*) qdialogbuttonbox.cpp:913
     #2 0x7f6d6b51436c in eventFilter qdialogbuttonbox.cpp:127
     #3 0x7f6d40c1a8f1 in QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) qcoreapplication.cpp:1248
     #4 0x7f6d690b23d5 in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3303
     #5 0x7f6d69132a3a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259
     #6 0x7f6d40c1da6a in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111
     #7 0x7f6d40c20473 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.cpp:1551
     #8 0x7f6d690fe76c in QApplicationPrivate::setActiveWindow(QWidget*) qapplication.cpp:1857
     #9 0x7f6d695ac796 in QWidgetPrivate::deactivateWidgetCleanup() qwidget.cpp:2326
     #10 0x7f6d6976f8ce in QWidgetPrivate::hide_sys() qwidget.cpp:8256
     #11 0x7f6d69814579 in QWidgetPrivate::hide_helper() qwidget.cpp:8199
     #12 0x7f6d69887c1f in QWidgetPrivate::setVisible(bool) qwidget.cpp:8406
     #13 0x7f6d69775d23 in QWidget::setVisible(bool) qwidget.cpp:8314
     #14 0x7f6d695fb018 in QWidget::hide() qwidget.cpp:8179
     #15 0x7f6d6981a183 in QWidgetPrivate::handleClose(QWidgetPrivate::CloseMode) qwidget.cpp:8580
     #16 0x7f6d699e6fc6 in QWidgetWindow::closeEvent(QCloseEvent*) qwidgetwindow.cpp:871
     #17 0x7f6d52ef9f5d in QWindow::event(QEvent*) qwindow.cpp:2721
     #18 0x7f6d69a575f8 in QWidgetWindow::event(QEvent*) qwidgetwindow.cpp:398
     #19 0x7f6d690b2491 in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3309
     #20 0x7f6d69132a3a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259
     #21 0x7f6d40c1da6a in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111
     #22 0x7f6d40c205b3 in QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) qcoreapplication.cpp:1565
     #23 0x7f6d5287415b in QGuiApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent*) qguiapplication.cpp:2911
     #24 0x7f6d528b543f in QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) qguiapplication.cpp:2259
     #25 0x7f6d52fb5b02 in QWindowSystemEventHandler::sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) qwindowsysteminterface.cpp:190
     #26 0x7f6d52fb5b02 in bool QWindowSystemHelper<QWindowSystemInterface::SynchronousDelivery>::handleEvent<QWindowSystemInterfacePrivate::CloseEvent, QWindow*>(QWindow*) qwindowsysteminterface.cpp:102
     #27 0x7f6d52fb5b02 in handleWindowSystemEvent<QWindowSystemInterfacePrivate::CloseEvent, QWindowSystemInterface::SynchronousDelivery, QWindow*> qwindowsysteminterface.cpp:138
     #28 0x7f6d52fb5b02 in bool QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::SynchronousDelivery>(QWindow*) qwindowsysteminterface.cpp:351
     #29 0x7f6d52cb6f1e in QPlatformWindow::close() qplatformwindow.cpp:348
     #30 0x7f6d52e7e158 in QWindow::close() qwindow.cpp:2449
     #31 0x7f6d6981b4d2 in QWidgetPrivate::close() qwidget.cpp:8632
     #32 0x7f6d698205c6 in QWidget::~QWidget() qwidget.cpp:1508
     #33 0x7f6d6b4f6bf0 in QDialogButtonBox::~QDialogButtonBox() qdialogbuttonbox.cpp:496

To fix, don't delay the Q_Q to until after the ignoreShowAndHide
check, since that woould be brittle. Instead, do as we for signal/slot
connections, which we disconnect explicitly in ~QDialogButtonBox(),
and delete the EventFilter explicitly there, too. This way, it's more
natural, and also prevents all those useless event filter invocations
from having to be processed later on.

Amends aff0915. The original code,
using QDialogButtonBox::eventFilter(), was not affected, since by the
time QDialogButtonBox was demoted to QWidget, QWidget::eventFilter(),
not QDialogButtonBox::eventFilter() would been invoked. Which just
goes to show that one needs to be very careful with delegating too
much responsibilites to the Private class, as it lives, fully derived,
until ~QWidget() executes.

Pick-to: 6.8 6.5
Change-Id: I04f36fd6d7d160932bfe1494fdff464786b85047
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
(cherry picked from commit dceff0a)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
qtprojectorg pushed a commit that referenced this pull request Apr 12, 2025
…howAndHide()

The event filter was still active when the QDialogButtonBox in its
destruction process had already been demoted to QWidget. The
ignoreShowAndHide guard came too late, because by the time we check
it, in Private::handleButtonShowAndHide(), we had already cast q_ptr
to QDialogButtonBox.

Says UBSan:

  qdialogbuttonbox_p.h:26:5: runtime error: downcast of address 0x7fffefab47e0 which does not point to an object of type 'QDialogButtonBox'
  0x7fffefab47e0: note: object is of type 'QWidget'
   00 00 00 00  28 c1 5b 6e 6d 7f 00 00  80 22 10 00 90 61 00 00  d8 c2 5b 6e 6d 7f 00 00  00 00 00 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QWidget'
     #0 0x7f6d6b51141d in QDialogButtonBoxPrivate::q_func() qdialogbuttonbox_p.h:26
     #1 0x7f6d6b51141d in QDialogButtonBoxPrivate::handleButtonShowAndHide(QAbstractButton*, QEvent*) qdialogbuttonbox.cpp:913
     #2 0x7f6d6b51436c in eventFilter qdialogbuttonbox.cpp:127
     #3 0x7f6d40c1a8f1 in QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) qcoreapplication.cpp:1248
     #4 0x7f6d690b23d5 in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3303
     #5 0x7f6d69132a3a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259
     #6 0x7f6d40c1da6a in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111
     #7 0x7f6d40c20473 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.cpp:1551
     #8 0x7f6d690fe76c in QApplicationPrivate::setActiveWindow(QWidget*) qapplication.cpp:1857
     #9 0x7f6d695ac796 in QWidgetPrivate::deactivateWidgetCleanup() qwidget.cpp:2326
     #10 0x7f6d6976f8ce in QWidgetPrivate::hide_sys() qwidget.cpp:8256
     #11 0x7f6d69814579 in QWidgetPrivate::hide_helper() qwidget.cpp:8199
     #12 0x7f6d69887c1f in QWidgetPrivate::setVisible(bool) qwidget.cpp:8406
     #13 0x7f6d69775d23 in QWidget::setVisible(bool) qwidget.cpp:8314
     #14 0x7f6d695fb018 in QWidget::hide() qwidget.cpp:8179
     #15 0x7f6d6981a183 in QWidgetPrivate::handleClose(QWidgetPrivate::CloseMode) qwidget.cpp:8580
     #16 0x7f6d699e6fc6 in QWidgetWindow::closeEvent(QCloseEvent*) qwidgetwindow.cpp:871
     #17 0x7f6d52ef9f5d in QWindow::event(QEvent*) qwindow.cpp:2721
     #18 0x7f6d69a575f8 in QWidgetWindow::event(QEvent*) qwidgetwindow.cpp:398
     #19 0x7f6d690b2491 in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3309
     #20 0x7f6d69132a3a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259
     #21 0x7f6d40c1da6a in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111
     #22 0x7f6d40c205b3 in QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) qcoreapplication.cpp:1565
     #23 0x7f6d5287415b in QGuiApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent*) qguiapplication.cpp:2911
     #24 0x7f6d528b543f in QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) qguiapplication.cpp:2259
     #25 0x7f6d52fb5b02 in QWindowSystemEventHandler::sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) qwindowsysteminterface.cpp:190
     #26 0x7f6d52fb5b02 in bool QWindowSystemHelper<QWindowSystemInterface::SynchronousDelivery>::handleEvent<QWindowSystemInterfacePrivate::CloseEvent, QWindow*>(QWindow*) qwindowsysteminterface.cpp:102
     #27 0x7f6d52fb5b02 in handleWindowSystemEvent<QWindowSystemInterfacePrivate::CloseEvent, QWindowSystemInterface::SynchronousDelivery, QWindow*> qwindowsysteminterface.cpp:138
     #28 0x7f6d52fb5b02 in bool QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::SynchronousDelivery>(QWindow*) qwindowsysteminterface.cpp:351
     #29 0x7f6d52cb6f1e in QPlatformWindow::close() qplatformwindow.cpp:348
     #30 0x7f6d52e7e158 in QWindow::close() qwindow.cpp:2449
     #31 0x7f6d6981b4d2 in QWidgetPrivate::close() qwidget.cpp:8632
     #32 0x7f6d698205c6 in QWidget::~QWidget() qwidget.cpp:1508
     #33 0x7f6d6b4f6bf0 in QDialogButtonBox::~QDialogButtonBox() qdialogbuttonbox.cpp:496

To fix, don't delay the Q_Q to until after the ignoreShowAndHide
check, since that woould be brittle. Instead, do as we for signal/slot
connections, which we disconnect explicitly in ~QDialogButtonBox(),
and delete the EventFilter explicitly there, too. This way, it's more
natural, and also prevents all those useless event filter invocations
from having to be processed later on.

Amends aff0915. The original code,
using QDialogButtonBox::eventFilter(), was not affected, since by the
time QDialogButtonBox was demoted to QWidget, QWidget::eventFilter(),
not QDialogButtonBox::eventFilter() would been invoked. Which just
goes to show that one needs to be very careful with delegating too
much responsibilites to the Private class, as it lives, fully derived,
until ~QWidget() executes.

Pick-to: 6.5
Change-Id: I04f36fd6d7d160932bfe1494fdff464786b85047
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
(cherry picked from commit dceff0a)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 6753ab4)
qtprojectorg pushed a commit that referenced this pull request Apr 13, 2025
…veButtonsFromMenuBar()

The function can be called from ~QMdiSubwindow(), and we checked for
QWidgetPrivate::data.in_destructor before proceeding with the removal
of buttons from the menubar, but we called
QPointer<QMdiSubwindow>::data()->window(), which, at this point in
time, had already been demoted to a QWidget:

Says UBSan:

  qpointer.h:75:14: runtime error: downcast of address 0x6040000aca10 which does not point to an object of type 'QMdiSubWindow'
   0x6040000aca10: note: object is of type 'QWidget'
    00 00 00 00  28 01 99 bc ff 7e 00 00  80 dc 0f 00 90 61 00 00  d8 02 99 bc ff 7e 00 00  00 00 be be
                 ^~~~~~~~~~~~~~~~~~~~~~~
                 vptr for 'QWidget'
       #0 0x7effb955f95a in QPointer<QMdiSubWindow>::data() const qpointer.h:75
       #1 0x7effb955f95a in QPointer<QMdiSubWindow>::operator->() const qpointer.h:79
       #2 0x7effb955f95a in QMdi::ControlContainer::removeButtonsFromMenuBar(QMenuBar*) qmdisubwindow.cpp:795
       #3 0x7effb9563031 in QMdi::ControlContainer::~ControlContainer() qmdisubwindow.cpp:717
       #4 0x7effb9566595 in QMdi::ControlContainer::~ControlContainer() qmdisubwindow.cpp:723
       #5 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #6 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #7 0x7effb95cc02c in QMdiSubWindow::~QMdiSubWindow() qmdisubwindow.cpp:2254
       #8 0x7effb95cc1d5 in QMdiSubWindow::~QMdiSubWindow() qmdisubwindow.cpp:2254
       #9 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #10 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #11 0x7effb7bffba5 in QWidget::~QWidget() qwidget.cpp:1584
       #12 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #13 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #14 0x7effb85f0dc5 in QFrame::~QFrame() qframe.cpp:235
       #15 0x7effb859c747 in QAbstractScrollArea::~QAbstractScrollArea() qabstractscrollarea.cpp:478
       #16 0x7effb93c08a6 in QMdiArea::~QMdiArea() qmdiarea.cpp:1703
       #17 0x7effb93c0e55 in QMdiArea::~QMdiArea() qmdiarea.cpp:1703
       #18 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #19 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #20 0x7effb920a425 in QMainWindow::~QMainWindow() qmainwindow.cpp:338

Fix by deleting the ControlContainer already from ~QMdiSubwindow(),
ie. when we have not yet been demoted to QWidget.

Amends the start of the public history.

Pick-to: 6.8 6.5 5.15
Change-Id: Ia43c857bc1842b2b4957cc79e00f790b045d8f94
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit 2e3d391)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
qtprojectorg pushed a commit that referenced this pull request Apr 13, 2025
The process by which the QDockAreaLayout changes a QDockAreaLayoutInfo
from representing a QWidget that's being deleted to representing a
QPlaceholderItem involves the construction of the latter from the
former. If a QDockWidget is being deleted, however, at the time the
QDockAreaLayout notices, the ex-QDockWidget has been demoted to a
QObject, causing the calls to QWidget member functions to be UB:

Says UBSan:

  qdockarealayout.cpp:46:25: runtime error: member call on address 0x7ffe74a429d0 which does not point to an object of type 'QWidget'
  0x7ffe74a429d0: note: object is of type 'QObject'
   33 7f 00 00  c0 ea 73 6e 33 7f 00 00  00 12 00 00 70 61 00 00  40 cd 41 83 33 7f 00 00  00 00 00 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QObject'
    #0 0x7f339546e251 in QPlaceHolderItem::QPlaceHolderItem(QWidget*) qdockarealayout.cpp:46
    #1 0x7f33955169a8 in QDockAreaLayoutInfo::takeAt(int*, int) qdockarealayout.cpp:1780
    #2 0x7f3395517175 in QDockAreaLayout::takeAt(int*, int) qdockarealayout.cpp:3432
    #3 0x7f33959e38a8 in QMainWindowLayoutState::takeAt(int, int*) qmainwindowlayout.cpp:927
    #4 0x7f33959e38a8 in QMainWindowLayoutState::takeAt(int, int*) qmainwindowlayout.cpp:919
    #5 0x7f3395a42cdd in QMainWindowLayout::takeAt(int) qmainwindowlayout.cpp:2238
    #6 0x7f3393fae246 in removeWidgetRecursively qlayout.cpp:485
    #7 0x7f3393fb8300 in QLayout::widgetEvent(QEvent*) qlayout.cpp:544
    #8 0x7f3393bde28a in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3298
    #9 0x7f3393c5f74a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259
    #10 0x7f336b784ada in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111
    #11 0x7f336b7874e3 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.cpp:1551
    #12 0x7f336bcc624a in QObjectPrivate::setParent_helper(QObject*) qobject.cpp:2271
    #13 0x7f336bccd76c in QObject::~QObject() qobject.cpp:1146
    #14 0x7f339434e126 in QWidget::~QWidget() qwidget.cpp:1584
    #15 0x7f33955b5815 in QDockWidget::~QDockWidget() qdockwidget.cpp:1362
    [...]

  qwidget.h:816:25: runtime error: member call on address 0x7ffe74a429d0 which does not point to an object of type 'QWidget'
  0x7ffe74a429d0: note: object is of type 'QObject'
   33 7f 00 00  c0 ea 73 6e 33 7f 00 00  00 12 00 00 70 61 00 00  40 cd 41 83 33 7f 00 00  00 00 00 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QObject'
    #0 0x7f339546e0bb in QWidget::isWindow() const qwidget.h:816
    #1 0x7f339546e0bb in QPlaceHolderItem::QPlaceHolderItem(QWidget*) qdockarealayout.cpp:47
    [... rest as above...]

Fix by dragging the setParent(nullptr) up into ~QDockWidget().

Ordinarily, that call happens only in ~QObject(). But that's what
caused the layout to react to the ChildRemoved element too late. When
doing it here, the dock widget is still itself, and all the
QDockAreaLayout machinery can still access its QWidget-ness.

Amends the start of the public history.

After consulting with QtWidgets maintainer, not picking to 5.15,
since, even though slim, there's a non-zero chance this might break
something, somewhere.

Pick-to: 6.8 6.5
Change-Id: I5472bbb0fcab9fb74272a1da6c2a2896226e12bb
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
(cherry picked from commit 2c67d47)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
qtprojectorg pushed a commit that referenced this pull request Apr 14, 2025
The process by which the QDockAreaLayout changes a QDockAreaLayoutInfo
from representing a QWidget that's being deleted to representing a
QPlaceholderItem involves the construction of the latter from the
former. If a QDockWidget is being deleted, however, at the time the
QDockAreaLayout notices, the ex-QDockWidget has been demoted to a
QObject, causing the calls to QWidget member functions to be UB:

Says UBSan:

  qdockarealayout.cpp:46:25: runtime error: member call on address 0x7ffe74a429d0 which does not point to an object of type 'QWidget'
  0x7ffe74a429d0: note: object is of type 'QObject'
   33 7f 00 00  c0 ea 73 6e 33 7f 00 00  00 12 00 00 70 61 00 00  40 cd 41 83 33 7f 00 00  00 00 00 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QObject'
    #0 0x7f339546e251 in QPlaceHolderItem::QPlaceHolderItem(QWidget*) qdockarealayout.cpp:46
    #1 0x7f33955169a8 in QDockAreaLayoutInfo::takeAt(int*, int) qdockarealayout.cpp:1780
    #2 0x7f3395517175 in QDockAreaLayout::takeAt(int*, int) qdockarealayout.cpp:3432
    #3 0x7f33959e38a8 in QMainWindowLayoutState::takeAt(int, int*) qmainwindowlayout.cpp:927
    #4 0x7f33959e38a8 in QMainWindowLayoutState::takeAt(int, int*) qmainwindowlayout.cpp:919
    #5 0x7f3395a42cdd in QMainWindowLayout::takeAt(int) qmainwindowlayout.cpp:2238
    #6 0x7f3393fae246 in removeWidgetRecursively qlayout.cpp:485
    #7 0x7f3393fb8300 in QLayout::widgetEvent(QEvent*) qlayout.cpp:544
    #8 0x7f3393bde28a in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3298
    #9 0x7f3393c5f74a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259
    #10 0x7f336b784ada in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111
    #11 0x7f336b7874e3 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.cpp:1551
    #12 0x7f336bcc624a in QObjectPrivate::setParent_helper(QObject*) qobject.cpp:2271
    #13 0x7f336bccd76c in QObject::~QObject() qobject.cpp:1146
    #14 0x7f339434e126 in QWidget::~QWidget() qwidget.cpp:1584
    #15 0x7f33955b5815 in QDockWidget::~QDockWidget() qdockwidget.cpp:1362
    [...]

  qwidget.h:816:25: runtime error: member call on address 0x7ffe74a429d0 which does not point to an object of type 'QWidget'
  0x7ffe74a429d0: note: object is of type 'QObject'
   33 7f 00 00  c0 ea 73 6e 33 7f 00 00  00 12 00 00 70 61 00 00  40 cd 41 83 33 7f 00 00  00 00 00 00
                ^~~~~~~~~~~~~~~~~~~~~~~
                vptr for 'QObject'
    #0 0x7f339546e0bb in QWidget::isWindow() const qwidget.h:816
    #1 0x7f339546e0bb in QPlaceHolderItem::QPlaceHolderItem(QWidget*) qdockarealayout.cpp:47
    [... rest as above...]

Fix by dragging the setParent(nullptr) up into ~QDockWidget().

Ordinarily, that call happens only in ~QObject(). But that's what
caused the layout to react to the ChildRemoved element too late. When
doing it here, the dock widget is still itself, and all the
QDockAreaLayout machinery can still access its QWidget-ness.

Amends the start of the public history.

After consulting with QtWidgets maintainer, not picking to 5.15,
since, even though slim, there's a non-zero chance this might break
something, somewhere.

Pick-to: 6.5
Change-Id: I5472bbb0fcab9fb74272a1da6c2a2896226e12bb
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
(cherry picked from commit 2c67d47)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 72dfe79)
qtprojectorg pushed a commit that referenced this pull request Apr 14, 2025
…veButtonsFromMenuBar()

The function can be called from ~QMdiSubwindow(), and we checked for
QWidgetPrivate::data.in_destructor before proceeding with the removal
of buttons from the menubar, but we called
QPointer<QMdiSubwindow>::data()->window(), which, at this point in
time, had already been demoted to a QWidget:

Says UBSan:

  qpointer.h:75:14: runtime error: downcast of address 0x6040000aca10 which does not point to an object of type 'QMdiSubWindow'
   0x6040000aca10: note: object is of type 'QWidget'
    00 00 00 00  28 01 99 bc ff 7e 00 00  80 dc 0f 00 90 61 00 00  d8 02 99 bc ff 7e 00 00  00 00 be be
                 ^~~~~~~~~~~~~~~~~~~~~~~
                 vptr for 'QWidget'
       #0 0x7effb955f95a in QPointer<QMdiSubWindow>::data() const qpointer.h:75
       #1 0x7effb955f95a in QPointer<QMdiSubWindow>::operator->() const qpointer.h:79
       #2 0x7effb955f95a in QMdi::ControlContainer::removeButtonsFromMenuBar(QMenuBar*) qmdisubwindow.cpp:795
       #3 0x7effb9563031 in QMdi::ControlContainer::~ControlContainer() qmdisubwindow.cpp:717
       #4 0x7effb9566595 in QMdi::ControlContainer::~ControlContainer() qmdisubwindow.cpp:723
       #5 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #6 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #7 0x7effb95cc02c in QMdiSubWindow::~QMdiSubWindow() qmdisubwindow.cpp:2254
       #8 0x7effb95cc1d5 in QMdiSubWindow::~QMdiSubWindow() qmdisubwindow.cpp:2254
       #9 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #10 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #11 0x7effb7bffba5 in QWidget::~QWidget() qwidget.cpp:1584
       #12 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #13 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #14 0x7effb85f0dc5 in QFrame::~QFrame() qframe.cpp:235
       #15 0x7effb859c747 in QAbstractScrollArea::~QAbstractScrollArea() qabstractscrollarea.cpp:478
       #16 0x7effb93c08a6 in QMdiArea::~QMdiArea() qmdiarea.cpp:1703
       #17 0x7effb93c0e55 in QMdiArea::~QMdiArea() qmdiarea.cpp:1703
       #18 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #19 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #20 0x7effb920a425 in QMainWindow::~QMainWindow() qmainwindow.cpp:338

Fix by deleting the ControlContainer already from ~QMdiSubwindow(),
ie. when we have not yet been demoted to QWidget.

Amends the start of the public history.

Pick-to: 6.5 5.15
Change-Id: Ia43c857bc1842b2b4957cc79e00f790b045d8f94
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit 2e3d391)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 0859415)
qtprojectorg pushed a commit that referenced this pull request Dec 12, 2025
Testcase: ./tst_qreadwritelock heavyLoadLocks

When the test run under release mode on arm64, all the spawned threads
may block without this fix. When the test run with optimization
enabled and assertions enabled and the assertions for !mutex.try_lock()
are removed from the entry of QReadWriteLockPrivate::
lockFor{Read,Write}, random assertion failures may happen without this
fix.

The reason for the race is because when a lock is uncontended locked and
being converted into a contended lock, no synchronization happens
between the initialization of new allocated QReadWriteLockPrivate object
and the use of the existing QReadWriteLockPrivate object in
lockFor{Read,Write}. QReadWriteLockPrivate objects are allocated from a
statically allocated freelist and it is of high probability that the
newly allocated object has just been released. The possible execution
order that leads to a data race is described as follows:

Suppose there are three threads T1, T2, and T3, and T1 holds the write
lock initially. T1 first releases the lock, and then gains the read
lock, while T2 tries to gain the write lock, and T3 tries to gain the
read lock. The interleaved execution order is as follows, where <- means
a normal memory write, <1> means a memory address of a
QReadWriteLockPrivate object, : means a return value, #n means a
synchronization point. For abberviation, wc denotes writerCount and rc
denotes readerCount. The .h/.c and the number in the parentheses denotes
the line number in qreadwritelock.h/.cpp.

T2                   T1                                       T3
                     unlock()                                 lockForRead()
                     d = d_ptr.loadRelaxed(): <1>   (.h 52)   d = d_ptr.loadRelaxed(): <1>  (.h 52)
                     <1>->mutex.lock()              (.c 393)  d = d_ptr.loadAcquire(): <1>  (.c 229)
                     <1> <-{wc = 0}(rc should be 0) (.c 397)  <1>->mutex.lock() ...         (.c 236)
                     d_ptr.storeRelease(null)   #1  (.c 409)
                     <1>->release()                 (.c 410)
                     <1>->mutex.unlock()        #2  (.c 412)
                     lockForRead()                            <1>->mutex.lock() returns  #2
                     d = d_ptr.loadRelaxed(): null  (.h 93)
lockForWrite()       d_ptr.testAndSetAcquire(1) #3  (.h 81)
d = d_ptr.loadRelaxed(): 1      (.h 116)
val = allocate -> <1>           (.c 321)
//                ^ suppose <1> is reused here
<1> <-{rc = 1}(wc should be 0)  (.c 325)
d_ptr.testAndSetOrdered(<1>) #5 (.c 326)
d = d_ptr.loadAcquire(): <1> #6 (.c 335)                      d_ptr.loadRelaxed(): <1>      (.c 237)
<1>->mutex.lock() ...           (.c 342)                      // Here T3 sees the d_ptr load result
                                                              // as <1>, which is the same as
                                                              // before, thinking it unchanged and
                                                              // thus continues to execute
                                                              // d->lockForRead().
                                                              // T3 here has no synchronization T2,
                                                              // but had synchronization with T1 at
                                                              // #2. So T3 may see the stale data
                                                              // previous written by T1 to <1>, i.e.
                                                              // wc = 0, rc = 0
                                                              <1> <-{rc = 1}                (.c 432)
                                                              <1>->mutex.unlock()        #4 (.c 248)
<1>->mutex.lock() returns    #4
d_ptr.loadRelaxed(): <1>        (.c 343)
// The same happens to T2 here, it continues
// to execute d->lockForWrite().
// T2 here is synchronized with T3 at #4,
// so T2 must see the data written by T3
// to <1>, i.e. wc = 0, rc = 1
<1>->writerCond.wait()          (.c 455)

After the above interleaved execution, T2 is blocked while T3 and T1 are
holding the read lock, but in the QReadWriteLockPrivate object, the
readerCount is 1, which is incorrect. This might further lead to
deadlock if readerCount becomes -1 after the two readers release the
lock or letting a writer to proceed when only one of the readers
releases the lock.

The fix changes the relaxed load of d_ptr in lockFor{Read,Write} after
the acquire of the mutex to an acquire load, to establish
synchronization with the release store of d_ptr when converting from an
uncontended lock to a contended lock.

Fixes: QTBUG-142321
Change-Id: I5a570471b52359dd65f309e644d9aacfd58ce943
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
qtprojectorg pushed a commit that referenced this pull request Dec 21, 2025
Testcase: ./tst_qreadwritelock heavyLoadLocks

When the test run under release mode on arm64, all the spawned threads
may block without this fix. When the test run with optimization
enabled and assertions enabled and the assertions for !mutex.try_lock()
are removed from the entry of QReadWriteLockPrivate::
lockFor{Read,Write}, random assertion failures may happen without this
fix.

The reason for the race is because when a lock is uncontended locked and
being converted into a contended lock, no synchronization happens
between the initialization of new allocated QReadWriteLockPrivate object
and the use of the existing QReadWriteLockPrivate object in
lockFor{Read,Write}. QReadWriteLockPrivate objects are allocated from a
statically allocated freelist and it is of high probability that the
newly allocated object has just been released. The possible execution
order that leads to a data race is described as follows:

Suppose there are three threads T1, T2, and T3, and T1 holds the write
lock initially. T1 first releases the lock, and then gains the read
lock, while T2 tries to gain the write lock, and T3 tries to gain the
read lock. The interleaved execution order is as follows, where <- means
a normal memory write, <1> means a memory address of a
QReadWriteLockPrivate object, : means a return value, #n means a
synchronization point. For abberviation, wc denotes writerCount and rc
denotes readerCount. The .h/.c and the number in the parentheses denotes
the line number in qreadwritelock.h/.cpp.

T2                   T1                                       T3
                     unlock()                                 lockForRead()
                     d = d_ptr.loadRelaxed(): <1>   (.h 52)   d = d_ptr.loadRelaxed(): <1>  (.h 52)
                     <1>->mutex.lock()              (.c 393)  d = d_ptr.loadAcquire(): <1>  (.c 229)
                     <1> <-{wc = 0}(rc should be 0) (.c 397)  <1>->mutex.lock() ...         (.c 236)
                     d_ptr.storeRelease(null)   #1  (.c 409)
                     <1>->release()                 (.c 410)
                     <1>->mutex.unlock()        #2  (.c 412)
                     lockForRead()                            <1>->mutex.lock() returns  #2
                     d = d_ptr.loadRelaxed(): null  (.h 93)
lockForWrite()       d_ptr.testAndSetAcquire(1) #3  (.h 81)
d = d_ptr.loadRelaxed(): 1      (.h 116)
val = allocate -> <1>           (.c 321)
//                ^ suppose <1> is reused here
<1> <-{rc = 1}(wc should be 0)  (.c 325)
d_ptr.testAndSetOrdered(<1>) #5 (.c 326)
d = d_ptr.loadAcquire(): <1> #6 (.c 335)                      d_ptr.loadRelaxed(): <1>      (.c 237)
<1>->mutex.lock() ...           (.c 342)                      // Here T3 sees the d_ptr load result
                                                              // as <1>, which is the same as
                                                              // before, thinking it unchanged and
                                                              // thus continues to execute
                                                              // d->lockForRead().
                                                              // T3 here has no synchronization T2,
                                                              // but had synchronization with T1 at
                                                              // #2. So T3 may see the stale data
                                                              // previous written by T1 to <1>, i.e.
                                                              // wc = 0, rc = 0
                                                              <1> <-{rc = 1}                (.c 432)
                                                              <1>->mutex.unlock()        #4 (.c 248)
<1>->mutex.lock() returns    #4
d_ptr.loadRelaxed(): <1>        (.c 343)
// The same happens to T2 here, it continues
// to execute d->lockForWrite().
// T2 here is synchronized with T3 at #4,
// so T2 must see the data written by T3
// to <1>, i.e. wc = 0, rc = 1
<1>->writerCond.wait()          (.c 455)

After the above interleaved execution, T2 is blocked while T3 and T1 are
holding the read lock, but in the QReadWriteLockPrivate object, the
readerCount is 1, which is incorrect. This might further lead to
deadlock if readerCount becomes -1 after the two readers release the
lock or letting a writer to proceed when only one of the readers
releases the lock.

The fix changes the relaxed load of d_ptr in lockFor{Read,Write} after
the acquire of the mutex to an acquire load, to establish
synchronization with the release store of d_ptr when converting from an
uncontended lock to a contended lock.

Fixes: QTBUG-142321
Change-Id: I5a570471b52359dd65f309e644d9aacfd58ce943
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 4fd8801)
qtprojectorg pushed a commit that referenced this pull request Feb 19, 2026
In the scenario described in the linked bug-report we are in an
environment where a host is configured to 'REJECT' our connection.
Specifically, the local nftables is configured to reject connections to
a given IP.

Because we are REJECTed and not DROPped it is generating an ICMP
"port unreachable" message. We are getting this message on the event
dispatcher, though our event code doesn't propagate the activation
reason:

(gdb) p *(GPollFD*)0x7fffec0017a0
$5 = {fd = 5, events = 28, revents = 28}
28 = 0x1c = POLLOUT | POLLERR | POLLHUP

We simply propagate that there was an event activating the socket, and
the socket notifier calls the nativeConnect again by way of this chain:

\#5  QNativeSocketEnginePrivate::nativeConnect
\#6  QNativeSocketEngine::connectToHost
\#7  QNativeSocketEngine::connectionNotification
\#8  QWriteNotifier::event
\#9  QCoreApplicationPrivate::notify_helper
\#10 QCoreApplication::notifyInternal2
\#11 QCoreApplication::sendEvent
\#12 socketNotifierSourceDispatch
\#13 g_main_dispatch

For some reason, this triggers it to send us the same event again. And
so the loop repeats, consuming excessive CPU time. Eventually the
connect() call returns with an error, ECONNREFUSED, ending the loop.

By not immediately calling connect() but instead using getsockopt with
SO_ERROR and then, if that doesn't return any error,
we can then call connect() to see if we have established connection.
If SO_ERROR, however, did return any error, we skip the connect() call
and handle the error as we would if it came from connect() itself,
avoiding the cycle and CPU usage.

Fixes: QTBUG-141419
Pick-to: 6.11
Change-Id: I8fcfd55e360a0f837ff8ae90784659d6299021f3
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
qtprojectorg pushed a commit that referenced this pull request Feb 19, 2026
In the scenario described in the linked bug-report we are in an
environment where a host is configured to 'REJECT' our connection.
Specifically, the local nftables is configured to reject connections to
a given IP.

Because we are REJECTed and not DROPped it is generating an ICMP
"port unreachable" message. We are getting this message on the event
dispatcher, though our event code doesn't propagate the activation
reason:

(gdb) p *(GPollFD*)0x7fffec0017a0
$5 = {fd = 5, events = 28, revents = 28}
28 = 0x1c = POLLOUT | POLLERR | POLLHUP

We simply propagate that there was an event activating the socket, and
the socket notifier calls the nativeConnect again by way of this chain:

\#5  QNativeSocketEnginePrivate::nativeConnect
\#6  QNativeSocketEngine::connectToHost
\#7  QNativeSocketEngine::connectionNotification
\#8  QWriteNotifier::event
\#9  QCoreApplicationPrivate::notify_helper
\#10 QCoreApplication::notifyInternal2
\#11 QCoreApplication::sendEvent
\#12 socketNotifierSourceDispatch
\#13 g_main_dispatch

For some reason, this triggers it to send us the same event again. And
so the loop repeats, consuming excessive CPU time. Eventually the
connect() call returns with an error, ECONNREFUSED, ending the loop.

By not immediately calling connect() but instead using getsockopt with
SO_ERROR and then, if that doesn't return any error,
we can then call connect() to see if we have established connection.
If SO_ERROR, however, did return any error, we skip the connect() call
and handle the error as we would if it came from connect() itself,
avoiding the cycle and CPU usage.

Fixes: QTBUG-141419
Change-Id: I8fcfd55e360a0f837ff8ae90784659d6299021f3
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 9d27af9)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
qtprojectorg pushed a commit that referenced this pull request Feb 20, 2026
Amends commit 97bd609, which inlined
the majority of the code and introduced the TSan code. That commit left
a comment saying the report would be wrong if the lock was contended. We
fix that by providing an out-of-line method that will tell us if this is
is a lock for reading (this includes recursive locks).

I believe this sequence of events causes TSan to complain:
 1. T0: lock for writing → sets regular StateLockedForWrite
 2. T1: attempt to lock for reading → goes into contended lock mode
 3. T0: unlock from writing →
    T1: activate reader
 4. T0: lock for reading again → stays in "contended" mode
 5. T1: unlock from reading
 5. T0: unlock from reading

Because we didn't inform TSan that it was a __tsan_mutex_read_lock in
step 5, it thinks it was for writing and considers it destroyed. So when
step 6 comes along and unlocks again, it prints the error that it wasn't
locked.

WARNING: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread) (pid=3376)
    #0 __tsan_mutex_pre_unlock <null> (libtsan.so.2+0x8def6) (BuildId: f86f06be33d22d7782bf90eeb243933a889060f9)
    #1 QtTsan::mutexPreUnlock(void*, unsigned int) thread/qtsan_impl.h:70 (qtbug-144288+0x4029a9) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #2 QBasicReadWriteLock::unlock() thread/qreadwritelock.h:58 (qtbug-144288+0x402dc1) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #3 QReadLocker::unlock() thread/qreadwritelock.h:225 (qtbug-144288+0x402fee) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #4 QReadLocker::~QReadLocker() thread/qreadwritelock.h:218 (qtbug-144288+0x402f59) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #5 workerFunction2() /tmp/qtbug-144288/main.cpp:21 (qtbug-144288+0x4023ed) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #6 main /tmp/qtbug-144288/main.cpp:45 (qtbug-144288+0x40257c) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)

  Location is global 'readWriteLock' of size 8 at 0x000000409178 (qtbug-144288+0x409178)

  Mutex M0 (0x000000409178) created at:
    #0 __tsan_mutex_pre_lock <null> (libtsan.so.2+0x8dcc6) (BuildId: f86f06be33d22d7782bf90eeb243933a889060f9)
    #1 QtTsan::mutexPreLock(void*, unsigned int) thread/qtsan_impl.h:60 (qtbug-144288+0x402909) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #2 QBasicReadWriteLock::tryLockForReadInternal(QDeadlineTimer, unsigned int) thread/qreadwritelock.h:91 (qtbug-144288+0x402a9a) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #3 QBasicReadWriteLock::lockForRead() thread/qreadwritelock.h:25 (qtbug-144288+0x402a9a)
    #4 QReadLocker::relock() thread/qreadwritelock.h:234 (qtbug-144288+0x40306f) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #5 QReadLocker::QReadLocker(QReadWriteLock*) thread/qreadwritelock.h:253 (qtbug-144288+0x403173) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #6 workerFunction2() /tmp/qtbug-144288/main.cpp:18 (qtbug-144288+0x4023cf) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #7 main /tmp/qtbug-144288/main.cpp:45 (qtbug-144288+0x40257c) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)

SUMMARY: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread) thread/qtsan_impl.h:70 in QtTsan::mutexPreUnlock(void*, unsigned int)

Pick-to: 6.11
Fixes: QTBUG-144288
Change-Id: I903aad084fa2d0c56511fffda1afe8602c299167
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
qtprojectorg pushed a commit that referenced this pull request Feb 21, 2026
Amends commit 97bd609, which inlined
the majority of the code and introduced the TSan code. That commit left
a comment saying the report would be wrong if the lock was contended. We
fix that by providing an out-of-line method that will tell us if this is
is a lock for reading (this includes recursive locks).

I believe this sequence of events causes TSan to complain:
 1. T0: lock for writing → sets regular StateLockedForWrite
 2. T1: attempt to lock for reading → goes into contended lock mode
 3. T0: unlock from writing →
    T1: activate reader
 4. T0: lock for reading again → stays in "contended" mode
 5. T1: unlock from reading
 5. T0: unlock from reading

Because we didn't inform TSan that it was a __tsan_mutex_read_lock in
step 5, it thinks it was for writing and considers it destroyed. So when
step 6 comes along and unlocks again, it prints the error that it wasn't
locked.

WARNING: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread) (pid=3376)
    #0 __tsan_mutex_pre_unlock <null> (libtsan.so.2+0x8def6) (BuildId: f86f06be33d22d7782bf90eeb243933a889060f9)
    #1 QtTsan::mutexPreUnlock(void*, unsigned int) thread/qtsan_impl.h:70 (qtbug-144288+0x4029a9) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #2 QBasicReadWriteLock::unlock() thread/qreadwritelock.h:58 (qtbug-144288+0x402dc1) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #3 QReadLocker::unlock() thread/qreadwritelock.h:225 (qtbug-144288+0x402fee) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #4 QReadLocker::~QReadLocker() thread/qreadwritelock.h:218 (qtbug-144288+0x402f59) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #5 workerFunction2() /tmp/qtbug-144288/main.cpp:21 (qtbug-144288+0x4023ed) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #6 main /tmp/qtbug-144288/main.cpp:45 (qtbug-144288+0x40257c) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)

  Location is global 'readWriteLock' of size 8 at 0x000000409178 (qtbug-144288+0x409178)

  Mutex M0 (0x000000409178) created at:
    #0 __tsan_mutex_pre_lock <null> (libtsan.so.2+0x8dcc6) (BuildId: f86f06be33d22d7782bf90eeb243933a889060f9)
    #1 QtTsan::mutexPreLock(void*, unsigned int) thread/qtsan_impl.h:60 (qtbug-144288+0x402909) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #2 QBasicReadWriteLock::tryLockForReadInternal(QDeadlineTimer, unsigned int) thread/qreadwritelock.h:91 (qtbug-144288+0x402a9a) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #3 QBasicReadWriteLock::lockForRead() thread/qreadwritelock.h:25 (qtbug-144288+0x402a9a)
    #4 QReadLocker::relock() thread/qreadwritelock.h:234 (qtbug-144288+0x40306f) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #5 QReadLocker::QReadLocker(QReadWriteLock*) thread/qreadwritelock.h:253 (qtbug-144288+0x403173) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #6 workerFunction2() /tmp/qtbug-144288/main.cpp:18 (qtbug-144288+0x4023cf) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)
    #7 main /tmp/qtbug-144288/main.cpp:45 (qtbug-144288+0x40257c) (BuildId: 41e65781957ab1509fb31b9106106f5c074f85f7)

SUMMARY: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread) thread/qtsan_impl.h:70 in QtTsan::mutexPreUnlock(void*, unsigned int)

Fixes: QTBUG-144288
Change-Id: I903aad084fa2d0c56511fffda1afe8602c299167
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
(cherry picked from commit 1d2c08a)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants