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.9 6.8 6.5 Change-Id: I4b765aed329211984c35c40fbc5648bf104990ce Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit 5aefe2d9a1d56f6134fcbbdff260c79082eea661) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
ee0cb525cd
commit
2b0ec367c7
@ -50,6 +50,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define Q_REFCOUNT_INITIALIZE_STATIC { Q_BASIC_ATOMIC_INITIALIZER(-1) }
|
#define Q_REFCOUNT_INITIALIZE_STATIC { Q_BASIC_ATOMIC_INITIALIZER(-1) }
|
||||||
|
#define Q_REFCOUNT_INITIALIZE_OWNED { Q_BASIC_ATOMIC_INITIALIZER(1) }
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
@ -3812,7 +3812,6 @@ QRegion::QRegion(const QRect &r, RegionType t)
|
|||||||
d = const_cast<QRegionData*>(&shared_empty);
|
d = const_cast<QRegionData*>(&shared_empty);
|
||||||
} else {
|
} else {
|
||||||
d = new QRegionData;
|
d = new QRegionData;
|
||||||
d->ref.initializeOwned();
|
|
||||||
if (t == Rectangle) {
|
if (t == Rectangle) {
|
||||||
d->qt_rgn = new QRegionPrivate(r);
|
d->qt_rgn = new QRegionPrivate(r);
|
||||||
} else if (t == Ellipse) {
|
} else if (t == Ellipse) {
|
||||||
@ -3831,7 +3830,6 @@ QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule)
|
|||||||
fillRule == Qt::WindingFill ? WindingRule : EvenOddRule);
|
fillRule == Qt::WindingFill ? WindingRule : EvenOddRule);
|
||||||
if (qt_rgn) {
|
if (qt_rgn) {
|
||||||
d = new QRegionData;
|
d = new QRegionData;
|
||||||
d->ref.initializeOwned();
|
|
||||||
d->qt_rgn = qt_rgn;
|
d->qt_rgn = qt_rgn;
|
||||||
} else {
|
} else {
|
||||||
d = const_cast<QRegionData*>(&shared_empty);
|
d = const_cast<QRegionData*>(&shared_empty);
|
||||||
@ -3854,7 +3852,6 @@ QRegion::QRegion(const QBitmap &bm)
|
|||||||
d = const_cast<QRegionData*>(&shared_empty);
|
d = const_cast<QRegionData*>(&shared_empty);
|
||||||
} else {
|
} else {
|
||||||
d = new QRegionData;
|
d = new QRegionData;
|
||||||
d->ref.initializeOwned();
|
|
||||||
d->qt_rgn = qt_bitmapToRegion(bm);
|
d->qt_rgn = qt_bitmapToRegion(bm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ Q_GUI_EXPORT
|
|||||||
void exec(const QByteArray &ba, int ver = 0, QDataStream::ByteOrder byteOrder = QDataStream::BigEndian);
|
void exec(const QByteArray &ba, int ver = 0, QDataStream::ByteOrder byteOrder = QDataStream::BigEndian);
|
||||||
#endif
|
#endif
|
||||||
struct QRegionData {
|
struct QRegionData {
|
||||||
QtPrivate::RefCount ref;
|
QtPrivate::RefCount ref = Q_REFCOUNT_INITIALIZE_OWNED;
|
||||||
QRegionPrivate *qt_rgn;
|
QRegionPrivate *qt_rgn;
|
||||||
};
|
};
|
||||||
struct QRegionData *d;
|
struct QRegionData *d;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user