summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <[email protected]>2025-06-06 16:40:48 +0200
committerMarc Mutz <[email protected]>2025-06-12 14:04:58 +0200
commit5aefe2d9a1d56f6134fcbbdff260c79082eea661 (patch)
tree805451e6af2847ef52ed9bc85257ec3d424942d7
parent3047d6a8a19fed870597d6c482f6c1a826ffb9f2 (diff)
QRegion: fix potential UB in QBasicAtomic initialization
Until C++17 (inclusive), a default-constructed std::atomic object can, officially, only be initialized with a call to std::atomic_init, for which QBasicAtomic doesn't have API. It is even unclear whether zero-initialization of static and thread-local objects will cause the object to be initialized. QRegion is using QtPrivate::RefCount, but that's just another wrapper around QBasicAtomic, so it has the same problems: it must always be initialized. So don't default-construct and then storeRelaxed() (via initializeOwned()), use NSDMI with (newly-added) Q_REFCOUNT_INITIALIZE_OWNED to avoid this dark language corner. Task-number: QTBUG-137465 Pick-to: 6.10 6.9 6.8 6.5 Change-Id: I4b765aed329211984c35c40fbc5648bf104990ce Reviewed-by: Thiago Macieira <[email protected]>
-rw-r--r--src/corelib/tools/qrefcount.h1
-rw-r--r--src/gui/painting/qregion.cpp3
-rw-r--r--src/gui/painting/qregion.h2
3 files changed, 2 insertions, 4 deletions
diff --git a/src/corelib/tools/qrefcount.h b/src/corelib/tools/qrefcount.h
index 9472716a723..da0942903d0 100644
--- a/src/corelib/tools/qrefcount.h
+++ b/src/corelib/tools/qrefcount.h
@@ -50,6 +50,7 @@ public:
}
#define Q_REFCOUNT_INITIALIZE_STATIC { Q_BASIC_ATOMIC_INITIALIZER(-1) }
+#define Q_REFCOUNT_INITIALIZE_OWNED { Q_BASIC_ATOMIC_INITIALIZER(1) }
QT_END_NAMESPACE
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 0d39ee05437..2b8c86ad84a 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -3812,7 +3812,6 @@ QRegion::QRegion(const QRect &r, RegionType t)
d = const_cast<QRegionData*>(&shared_empty);
} else {
d = new QRegionData;
- d->ref.initializeOwned();
if (t == Rectangle) {
d->qt_rgn = new QRegionPrivate(r);
} else if (t == Ellipse) {
@@ -3831,7 +3830,6 @@ QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule)
fillRule == Qt::WindingFill ? WindingRule : EvenOddRule);
if (qt_rgn) {
d = new QRegionData;
- d->ref.initializeOwned();
d->qt_rgn = qt_rgn;
} else {
d = const_cast<QRegionData*>(&shared_empty);
@@ -3854,7 +3852,6 @@ QRegion::QRegion(const QBitmap &bm)
d = const_cast<QRegionData*>(&shared_empty);
} else {
d = new QRegionData;
- d->ref.initializeOwned();
d->qt_rgn = qt_bitmapToRegion(bm);
}
}
diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h
index 4b852815f32..f7f35a8725b 100644
--- a/src/gui/painting/qregion.h
+++ b/src/gui/painting/qregion.h
@@ -121,7 +121,7 @@ Q_GUI_EXPORT
void exec(const QByteArray &ba, int ver = 0, QDataStream::ByteOrder byteOrder = QDataStream::BigEndian);
#endif
struct QRegionData {
- QtPrivate::RefCount ref;
+ QtPrivate::RefCount ref = Q_REFCOUNT_INITIALIZE_OWNED;
QRegionPrivate *qt_rgn;
};
struct QRegionData *d;