summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qmetatype.cpp
diff options
context:
space:
mode:
authorJoão Abecasis <joao.abecasis@nokia.com>2012-01-30 14:50:04 +0100
committerQt by Nokia <qt-info@nokia.com>2012-02-07 09:47:51 +0100
commit5a92dd612472378ec329d380fdc8fe609478b06c (patch)
tree3f48a2970f9a0d7f81b09e3c91035a250ee0c05c /src/corelib/kernel/qmetatype.cpp
parentb8cf1d6bdcaefaa610014a742808af3ab2c6fe06 (diff)
Detect incompatibilities in repeated type registration
QMetaType used to register a typeName and factory functions for creation/destruction of objects. While it would be possible for a single type name to be registered matching different actual types and memory layouts, there was little that could be done about it. Now that QMetaType is tracking type information with a direct impact on data layout and ABI (size and type flags) it is important that we check and detect binary incompatibilities as early as possible. [Such incompatibilities could arise from type name re-use (technically, ODR violations) or, more commonly, as version mismatch between different shared libraries or plugins.] Only type size and flags are checked as function pointers to inline and template or otherwise non-exported functions could trivially differ across translation units and shared libraries. When registering typedef types, a check is made to ensure the same name doesn't get registered as different types. Change-Id: I8211c3de75d4854ce8fafdb620d3a931c206e0c3 Reviewed-by: Olivier Goffart <ogoffart@woboq.com> Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@nokia.com> Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Diffstat (limited to 'src/corelib/kernel/qmetatype.cpp')
-rw-r--r--src/corelib/kernel/qmetatype.cpp66
1 files changed, 49 insertions, 17 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index b31bece376..a6b1599444 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -465,6 +465,8 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
normalizedTypeName.size());
+ int previousSize = 0;
+ int previousFlags = 0;
if (!idx) {
QWriteLocker locker(customTypesLock());
idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
@@ -485,8 +487,33 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
inf.flags = flags;
idx = ct->size() + User;
ct->append(inf);
+ return idx;
}
+
+ if (idx >= User) {
+ previousSize = ct->at(idx - User).size;
+ previousFlags = ct->at(idx - User).flags;
+ }
+ }
+
+ if (idx < User) {
+ previousSize = QMetaType::sizeOf(idx);
+ previousFlags = QMetaType::typeFlags(idx);
+ }
+
+ if (previousSize != size) {
+ qFatal("QMetaType::registerType: Binary compatibility break "
+ "-- Size mismatch for type '%s' [%i]. Previously registered "
+ "size %i, now registering size %i.",
+ normalizedTypeName.constData(), idx, previousSize, size);
}
+ if (previousFlags != flags) {
+ qFatal("QMetaType::registerType: Binary compatibility break "
+ "-- Type flags for type '%s' [%i] don't match. Previously "
+ "registered TypeFlags(0x%x), now registering TypeFlags(0x%x).",
+ normalizedTypeName.constData(), idx, previousFlags, int(flags));
+ }
+
return idx;
}
@@ -510,25 +537,30 @@ int QMetaType::registerTypedef(const char* typeName, int aliasId)
int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
normalizedTypeName.size());
- if (idx) {
- Q_ASSERT(idx == aliasId);
- return idx;
- }
-
- QWriteLocker locker(customTypesLock());
- idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
- normalizedTypeName.size());
+ if (!idx) {
+ QWriteLocker locker(customTypesLock());
+ idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
+ normalizedTypeName.size());
- if (idx)
- return idx;
+ if (!idx) {
+ QCustomTypeInfo inf;
+ inf.typeName = normalizedTypeName;
+ inf.alias = aliasId;
+ inf.creator = 0;
+ inf.deleter = 0;
+ ct->append(inf);
+ return aliasId;
+ }
+ }
- QCustomTypeInfo inf;
- inf.typeName = normalizedTypeName;
- inf.alias = aliasId;
- inf.creator = 0;
- inf.deleter = 0;
- ct->append(inf);
- return aliasId;
+ if (idx != aliasId) {
+ qFatal("QMetaType::registerTypedef: Binary compatibility break "
+ "-- Type name '%s' previously registered as typedef of '%s' [%i], "
+ "now registering as typedef of '%s' [%i].",
+ normalizedTypeName.constData(), QMetaType::typeName(idx), idx,
+ QMetaType::typeName(aliasId), aliasId);
+ }
+ return idx;
}
/*!