Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
None
-
6.0
-
None
-
-
359616066e64eed947c6c91cb8902285ed79dd0d (qt/qtbase/dev)
Description
The following example reproduces the crash reliably when running on macOS:
#include <QApplication> #include <QMainWindow> #include <QTabWidget> #include <QVBoxLayout> class TestWindow : public QMainWindow { public: TestWindow(QWidget *parent = nullptr) : QMainWindow(parent) { QTabWidget* tw = new QTabWidget; QWidget* w1 = new QWidget; QWidget* w2 = new QWidget; tw->addTab( w1, "One" ); tw->addTab( w2, "Two"); tw->setMovable(true); QVBoxLayout* l = new QVBoxLayout; l->addWidget(tw); QWidget* w = new QWidget; w->setLayout(l); setCentralWidget(w); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); TestWindow w; w.show(); return a.exec(); }
Drag the two tabs around a few times, it will crash with the following stack trace:
libQt6Core_debug.6.dylib!std::__1::__atomic_base<int, false>::load(std::__1::memory_order) const (/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/atomic:926) libQt6Core_debug.6.dylib!int QAtomicOps<int>::loadRelaxed<int>(std::__1::atomic<int> const&) (/Users/vohi/qt/dev/qtbase/src/corelib/thread/qatomic_cxx11.h:239) libQt6Core_debug.6.dylib!QBasicAtomicInteger<int>::loadRelaxed() const (/Users/vohi/qt/dev/qtbase/src/corelib/thread/qbasicatomic.h:107) libQt6Core_debug.6.dylib!QtPrivate::RefCount::ref() (/Users/vohi/qt/dev/qtbase/src/corelib/tools/qrefcount.h:55) libQt6Core_debug.6.dylib!QMetaType::QMetaType(QtPrivate::QMetaTypeInterface*) (/Users/vohi/qt/dev/qtbase/src/corelib/kernel/qmetatype.cpp:683) libQt6Core_debug.6.dylib!QMetaType::QMetaType(QtPrivate::QMetaTypeInterface*) (/Users/vohi/qt/dev/qtbase/src/corelib/kernel/qmetatype.cpp:681) libQt6Core_debug.6.dylib!QVariant::Private::type() const (/Users/vohi/qt/dev/qtbase/src/corelib/kernel/qvariant.h:448) libQt6Core_debug.6.dylib!QVariant::Private::Private(QVariant::Private const&) (/Users/vohi/qt/dev/qtbase/src/corelib/kernel/qvariant.h:405) libQt6Core_debug.6.dylib!QVariant::QVariant(QVariant const&) (/Users/vohi/qt/dev/qtbase/src/corelib/kernel/qvariant.cpp:1783) libQt6Core_debug.6.dylib!QVariant::QVariant(QVariant const&) (/Users/vohi/qt/dev/qtbase/src/corelib/kernel/qvariant.cpp:1784) libQt6Core_debug.6.dylib!std::__1::pair<double, QVariant>::pair(std::__1::pair<double, QVariant> const&) (/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/utility:328) libQt6Core_debug.6.dylib!std::__1::pair<double, QVariant>::pair(std::__1::pair<double, QVariant> const&) (/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/utility:328) libQt6Core_debug.6.dylib!QtPrivate::QGenericArrayOps<std::__1::pair<double, QVariant> >::copyAppend(std::__1::pair<double, QVariant> const*, std::__1::pair<double, QVariant> const*) (/Users/vohi/qt/dev/qtbase/src/corelib/tools/qarraydataops.h:276) libQt6Core_debug.6.dylib!QArrayDataPointer<std::__1::pair<double, QVariant> >::clone(QFlags<QArrayData::ArrayOption>) const (/Users/vohi/qt/dev/qtbase/src/corelib/tools/qarraydatapointer.h:218) libQt6Core_debug.6.dylib!QArrayDataPointer<std::__1::pair<double, QVariant> >::detach() (/Users/vohi/qt/dev/qtbase/src/corelib/tools/qarraydatapointer.h:175) libQt6Core_debug.6.dylib!QList<std::__1::pair<double, QVariant> >::detach() (/Users/vohi/qt/dev/qtbase/src/corelib/tools/qlist.h:210) libQt6Core_debug.6.dylib!QList<std::__1::pair<double, QVariant> >::begin() (/Users/vohi/qt/dev/qtbase/src/corelib/tools/qlist.h:358) libQt6Core_debug.6.dylib!QVariantAnimationPrivate::setValueAt(double, QVariant const&) (/Users/vohi/qt/dev/qtbase/src/corelib/animation/qvariantanimation.cpp:316) libQt6Core_debug.6.dylib!QVariantAnimation::setKeyValueAt(double, QVariant const&) (/Users/vohi/qt/dev/qtbase/src/corelib/animation/qvariantanimation.cpp:585) libQt6Core_debug.6.dylib!QVariantAnimation::setStartValue(QVariant const&) (/Users/vohi/qt/dev/qtbase/src/corelib/animation/qvariantanimation.cpp:532)
This is a use-after-free issue, the Tab::animation instance has been deleted. This happens in QTabBarPrivate::~Tab:
~Tab() { delete animation; }
And a call stack to that during the drag-operation is:
libQt6Widgets_debug.6.dylib!QTabBarPrivate::Tab::~Tab() (/Users/vohi/qt/dev/qtbase/src/widgets/widgets/qtabbar_p.h:144) libQt6Widgets_debug.6.dylib!QTabBarPrivate::Tab::~Tab() (/Users/vohi/qt/dev/qtbase/src/widgets/widgets/qtabbar_p.h:143) libQt6Widgets_debug.6.dylib!std::__1::enable_if<(is_move_constructible<QTabBarPrivate::Tab>::value) && (is_move_assignable<QTabBarPrivate::Tab>::value), void>::type std::__1::swap<QTabBarPrivate::Tab>(QTabBarPrivate::Tab&, QTabBarPrivate::Tab&) (/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/type_traits:4529) libQt6Widgets_debug.6.dylib!QTabBarPrivate::Tab* std::__1::__rotate_forward<QTabBarPrivate::Tab*>(QTabBarPrivate::Tab*, QTabBarPrivate::Tab*, QTabBarPrivate::Tab*) (/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:2271) libQt6Widgets_debug.6.dylib!QTabBarPrivate::Tab* std::__1::__rotate<QTabBarPrivate::Tab*>(QTabBarPrivate::Tab*, QTabBarPrivate::Tab*, QTabBarPrivate::Tab*, std::__1::random_access_iterator_tag) (/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:2395) libQt6Widgets_debug.6.dylib!QTabBarPrivate::Tab* std::__1::rotate<QTabBarPrivate::Tab*>(QTabBarPrivate::Tab*, QTabBarPrivate::Tab*, QTabBarPrivate::Tab*) (/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:2407) libQt6Widgets_debug.6.dylib!QList<QTabBarPrivate::Tab>::move(int, int) (/Users/vohi/qt/dev/qtbase/src/corelib/tools/qlist.h:352) libQt6Widgets_debug.6.dylib!QTabBar::moveTab(int, int) (/Users/vohi/qt/dev/qtbase/src/widgets/widgets/qtabbar.cpp:2039) libQt6Widgets_debug.6.dylib!QTabBarPrivate::slide(int, int) (/Users/vohi/qt/dev/qtbase/src/widgets/widgets/qtabbar.cpp:2080) libQt6Widgets_debug.6.dylib!QTabBar::mouseMoveEvent(QMouseEvent*) (/Users/vohi/qt/dev/qtbase/src/widgets/widgets/qtabbar.cpp:2192) libQt6Widgets_debug.6.dylib!QWidget::event(QEvent*) (/Users/vohi/qt/dev/qtbase/src/widgets/kernel/qwidget.cpp:8601) libQt6Widgets_debug.6.dylib!QTabBar::event(QEvent*)
So, it would seem that QList<QTabBarPrivate::Tab>::move deletes tab instances, which destructs the animation object.
Assumption is that this is because the type doesn't implement a move constructor, but it's a very bad side effect of the change of the QList implementation to be a vector.
Attachments
Issue Links
- Is tested by
-
QTBUG-85301 dragging the tab will cause it to be selected
- Reported