QObjectPrivate: encode the version number in the constructor parameters
Instead of allowing the code to start and then possibly fail at runtime. This isn't a 100% sure solution because it's a function call. With lazy symbol binding on some OSes, the mistake won't be noticed until the function call is attempted. However, most OSes now resolve *all* calls at load time so they can mark the GOT (or equivalent) pages read-only, meaning the loading of the library will fail. qversiontagging_p.h is a more sure way in OSes / executable formats it works on. Change-Id: If7867a37256b7141001dfffd9bd299bb1bbd7c63 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
parent
1b85143d21
commit
744fda9cb4
@ -158,11 +158,9 @@ QMetaObject *QObjectData::dynamicMetaObject() const
|
|||||||
return metaObject->toDynamicMetaObject(q_ptr);
|
return metaObject->toDynamicMetaObject(q_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
QObjectPrivate::QObjectPrivate(int version)
|
QObjectPrivate::QObjectPrivate(decltype(QObjectPrivateVersion))
|
||||||
: threadData(nullptr), currentChildBeingDeleted(nullptr)
|
: threadData(nullptr), currentChildBeingDeleted(nullptr)
|
||||||
{
|
{
|
||||||
checkForIncompatibleLibraryVersion(version);
|
|
||||||
|
|
||||||
// QObjectData initialization
|
// QObjectData initialization
|
||||||
q_ptr = nullptr;
|
q_ptr = nullptr;
|
||||||
parent = nullptr; // no parent yet. It is set by setParent()
|
parent = nullptr; // no parent yet. It is set by setParent()
|
||||||
|
@ -39,6 +39,19 @@ QT_BEGIN_NAMESPACE
|
|||||||
#define QT_ANONYMOUS_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_anonymous_private_property, d, text)
|
#define QT_ANONYMOUS_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_anonymous_private_property, d, text)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define QT_CONCAT(B, M, m, u) QT_CONCAT2(B, M, m, u)
|
||||||
|
#define QT_CONCAT2(B, M, m, u) B ## M ## _ ## m ## _ ## u
|
||||||
|
#if defined(QT_BUILD_INTERNAL) && !QT_CONFIG(elf_private_full_version)
|
||||||
|
// Don't check the version parameter in internal builds.
|
||||||
|
// This allows incompatible versions to be loaded, possibly for testing.
|
||||||
|
enum QObjectPrivateVersionEnum
|
||||||
|
#else
|
||||||
|
enum QT_CONCAT(QtPrivate_, QT_VERSION_MAJOR, QT_VERSION_MINOR, QT_VERSION_PATCH)
|
||||||
|
#endif
|
||||||
|
{ QObjectPrivateVersion = QT_VERSION };
|
||||||
|
#undef QT_CONCAT
|
||||||
|
#undef QT_CONCAT2
|
||||||
|
|
||||||
class QVariant;
|
class QVariant;
|
||||||
class QThreadData;
|
class QThreadData;
|
||||||
class QObjectConnectionListVector;
|
class QObjectConnectionListVector;
|
||||||
@ -58,8 +71,6 @@ void Q_CORE_EXPORT qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callb
|
|||||||
|
|
||||||
extern Q_CORE_EXPORT QBasicAtomicPointer<QSignalSpyCallbackSet> qt_signal_spy_callback_set;
|
extern Q_CORE_EXPORT QBasicAtomicPointer<QSignalSpyCallbackSet> qt_signal_spy_callback_set;
|
||||||
|
|
||||||
enum { QObjectPrivateVersion = QT_VERSION };
|
|
||||||
|
|
||||||
class Q_CORE_EXPORT QAbstractDeclarativeData
|
class Q_CORE_EXPORT QAbstractDeclarativeData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -130,14 +141,12 @@ public:
|
|||||||
linked list.
|
linked list.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QObjectPrivate(int version = QObjectPrivateVersion);
|
QObjectPrivate(decltype(QObjectPrivateVersion) version = QObjectPrivateVersion);
|
||||||
virtual ~QObjectPrivate();
|
virtual ~QObjectPrivate();
|
||||||
void deleteChildren();
|
void deleteChildren();
|
||||||
// used to clear binding storage early in ~QObject
|
// used to clear binding storage early in ~QObject
|
||||||
void clearBindingStorage();
|
void clearBindingStorage();
|
||||||
|
|
||||||
inline void checkForIncompatibleLibraryVersion(int version) const;
|
|
||||||
|
|
||||||
void setParent_helper(QObject *);
|
void setParent_helper(QObject *);
|
||||||
void moveToThread_helper();
|
void moveToThread_helper();
|
||||||
void setThreadData_helper(QThreadData *currentData, QThreadData *targetData, QBindingStatus *status);
|
void setThreadData_helper(QThreadData *currentData, QThreadData *targetData, QBindingStatus *status);
|
||||||
@ -216,28 +225,6 @@ public:
|
|||||||
QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
|
QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Catch mixing of incompatible library versions.
|
|
||||||
|
|
||||||
Should be called from the constructor of every non-final subclass
|
|
||||||
of QObjectPrivate, to ensure we catch incompatibilities between
|
|
||||||
the intermediate base and subclasses thereof.
|
|
||||||
*/
|
|
||||||
inline void QObjectPrivate::checkForIncompatibleLibraryVersion(int version) const
|
|
||||||
{
|
|
||||||
#if defined(QT_BUILD_INTERNAL)
|
|
||||||
// Don't check the version parameter in internal builds.
|
|
||||||
// This allows incompatible versions to be loaded, possibly for testing.
|
|
||||||
Q_UNUSED(version);
|
|
||||||
#else
|
|
||||||
if (Q_UNLIKELY(version != QObjectPrivateVersion)) {
|
|
||||||
qFatal("Cannot mix incompatible Qt library (%d.%d.%d) with this library (%d.%d.%d)",
|
|
||||||
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff,
|
|
||||||
(QObjectPrivateVersion >> 16) & 0xff, (QObjectPrivateVersion >> 8) & 0xff, QObjectPrivateVersion & 0xff);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const
|
inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const
|
||||||
{
|
{
|
||||||
return !isDeletingChildren && declarativeData && QAbstractDeclarativeData::isSignalConnected
|
return !isDeletingChildren && declarativeData && QAbstractDeclarativeData::isSignalConnected
|
||||||
|
@ -25,7 +25,7 @@ using namespace Qt::StringLiterals;
|
|||||||
// we use a tighter limit for the variables range.
|
// we use a tighter limit for the variables range.
|
||||||
const qreal g_offset = (sizeof(qreal) == sizeof(double)) ? QWIDGETSIZE_MAX : QWIDGETSIZE_MAX / 32;
|
const qreal g_offset = (sizeof(qreal) == sizeof(double)) ? QWIDGETSIZE_MAX : QWIDGETSIZE_MAX / 32;
|
||||||
|
|
||||||
QGraphicsAnchorPrivate::QGraphicsAnchorPrivate(int version)
|
QGraphicsAnchorPrivate::QGraphicsAnchorPrivate(decltype(QObjectPrivateVersion) version)
|
||||||
: QObjectPrivate(version), layoutPrivate(nullptr), data(nullptr),
|
: QObjectPrivate(version), layoutPrivate(nullptr), data(nullptr),
|
||||||
sizePolicy(QSizePolicy::Fixed), preferredSize(0),
|
sizePolicy(QSizePolicy::Fixed), preferredSize(0),
|
||||||
hasSize(true)
|
hasSize(true)
|
||||||
|
@ -313,7 +313,7 @@ class QGraphicsAnchorPrivate : public QObjectPrivate
|
|||||||
Q_DECLARE_PUBLIC(QGraphicsAnchor)
|
Q_DECLARE_PUBLIC(QGraphicsAnchor)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QGraphicsAnchorPrivate(int version = QObjectPrivateVersion);
|
explicit QGraphicsAnchorPrivate(decltype(QObjectPrivateVersion) = QObjectPrivateVersion);
|
||||||
~QGraphicsAnchorPrivate();
|
~QGraphicsAnchorPrivate();
|
||||||
|
|
||||||
void setSpacing(qreal value);
|
void setSpacing(qreal value);
|
||||||
|
@ -103,7 +103,7 @@ static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
|
|||||||
|
|
||||||
extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
|
extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
|
||||||
|
|
||||||
QWidgetPrivate::QWidgetPrivate(int version)
|
QWidgetPrivate::QWidgetPrivate(decltype(QObjectPrivateVersion) version)
|
||||||
: QObjectPrivate(version)
|
: QObjectPrivate(version)
|
||||||
, focus_next(nullptr)
|
, focus_next(nullptr)
|
||||||
, focus_prev(nullptr)
|
, focus_prev(nullptr)
|
||||||
@ -164,16 +164,6 @@ QWidgetPrivate::QWidgetPrivate(int version)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef QT_BUILD_INTERNAL
|
|
||||||
// Don't check the version parameter in internal builds.
|
|
||||||
// This allows incompatible versions to be loaded, possibly for testing.
|
|
||||||
Q_UNUSED(version);
|
|
||||||
#else
|
|
||||||
if (Q_UNLIKELY(version != QObjectPrivateVersion))
|
|
||||||
qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)",
|
|
||||||
version, QObjectPrivateVersion);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
willBeWidget = true; // used in QObject's ctor
|
willBeWidget = true; // used in QObject's ctor
|
||||||
memset(high_attributes, 0, sizeof(high_attributes));
|
memset(high_attributes, 0, sizeof(high_attributes));
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ public:
|
|||||||
Q_ENUM(Direction)
|
Q_ENUM(Direction)
|
||||||
|
|
||||||
// Functions.
|
// Functions.
|
||||||
explicit QWidgetPrivate(int version = QObjectPrivateVersion);
|
explicit QWidgetPrivate(decltype(QObjectPrivateVersion) = QObjectPrivateVersion);
|
||||||
~QWidgetPrivate();
|
~QWidgetPrivate();
|
||||||
|
|
||||||
static QWidgetPrivate *get(QWidget *w) { return w->d_func(); }
|
static QWidgetPrivate *get(QWidget *w) { return w->d_func(); }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user