QMetaObjectBuilder: Always set Data::metatypes
The array of metatypes should always contain at least one entry (for the metatype of the current metaobject itself). This prevents crashes in the case of a metaobject without meta-methods and properties (as observed in Qt for Python). Pick-to: 6.2 6.3 Change-Id: I7a6fb316eea48c4852b6f1c26e0a930aeba4c799 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>bb10
parent
9d4e6d560a
commit
ef0e13257d
|
|
@ -1439,41 +1439,39 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
|||
size += sizeof(SuperData) * (d->relatedMetaObjects.size() + 1);
|
||||
}
|
||||
|
||||
if (d->properties.size() > 0 || d->methods.size() > 0 || d->constructors.size() > 0) {
|
||||
ALIGN(size, QtPrivate::QMetaTypeInterface *);
|
||||
auto types = reinterpret_cast<QtPrivate::QMetaTypeInterface **>(buf + size);
|
||||
if constexpr (mode == Construct) {
|
||||
meta->d.metaTypes = types;
|
||||
for (const auto &prop : d->properties) {
|
||||
QMetaType mt = prop.metaType;
|
||||
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
|
||||
types++;
|
||||
}
|
||||
// add metatype interface for this metaobject - must be null
|
||||
// as we can't know our metatype
|
||||
*types = nullptr;
|
||||
ALIGN(size, QtPrivate::QMetaTypeInterface *);
|
||||
auto types = reinterpret_cast<QtPrivate::QMetaTypeInterface **>(buf + size);
|
||||
if constexpr (mode == Construct) {
|
||||
meta->d.metaTypes = types;
|
||||
for (const auto &prop : d->properties) {
|
||||
QMetaType mt = prop.metaType;
|
||||
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
|
||||
types++;
|
||||
for (const auto &method: d->methods) {
|
||||
QMetaType mt(QMetaType::fromName(method.returnType).id());
|
||||
}
|
||||
// add metatype interface for this metaobject - must be null
|
||||
// as we can't know our metatype
|
||||
*types = nullptr;
|
||||
types++;
|
||||
for (const auto &method: d->methods) {
|
||||
QMetaType mt(QMetaType::fromName(method.returnType).id());
|
||||
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
|
||||
types++;
|
||||
for (const auto ¶meterType: method.parameterTypes()) {
|
||||
QMetaType mt = QMetaType::fromName(parameterType);
|
||||
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
|
||||
types++;
|
||||
}
|
||||
}
|
||||
for (const auto &constructor : d->constructors) {
|
||||
for (const auto ¶meterType : constructor.parameterTypes()) {
|
||||
QMetaType mt = QMetaType::fromName(parameterType);
|
||||
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
|
||||
types++;
|
||||
for (const auto ¶meterType: method.parameterTypes()) {
|
||||
QMetaType mt = QMetaType::fromName(parameterType);
|
||||
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
|
||||
types++;
|
||||
}
|
||||
}
|
||||
for (const auto &constructor : d->constructors) {
|
||||
for (const auto ¶meterType : constructor.parameterTypes()) {
|
||||
QMetaType mt = QMetaType::fromName(parameterType);
|
||||
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
|
||||
types++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// parameterMetaTypesIndex is equal to the total number of metatypes
|
||||
size += sizeof(QMetaType) * parameterMetaTypesIndex;
|
||||
}
|
||||
// parameterMetaTypesIndex is equal to the total number of metatypes
|
||||
size += sizeof(QMetaType) * parameterMetaTypesIndex;
|
||||
|
||||
// Align the final size and return it.
|
||||
ALIGN(size, void *);
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ private slots:
|
|||
|
||||
void cleanupTestCase();
|
||||
|
||||
void ownMetaTypeNoProperties();
|
||||
|
||||
private:
|
||||
static bool checkForSideEffects
|
||||
(const QMetaObjectBuilder& builder,
|
||||
|
|
@ -1657,6 +1659,16 @@ void tst_QMetaObjectBuilder::propertyMetaType()
|
|||
free(mo);
|
||||
}
|
||||
|
||||
void tst_QMetaObjectBuilder::ownMetaTypeNoProperties()
|
||||
{
|
||||
QMetaObjectBuilder builder;
|
||||
builder.setClassName("NoProperties");
|
||||
auto mo = builder.toMetaObject();
|
||||
auto cleanup = qScopeGuard([&](){ free(mo); });
|
||||
// own metatype should be invalid, as the dynamic metaobject has not been registered
|
||||
QVERIFY(!mo->metaType().isValid());// should not crash
|
||||
}
|
||||
|
||||
void tst_QMetaObjectBuilder::cleanupTestCase()
|
||||
{
|
||||
for (QMetaObject *obj: dynamicMetaObjectsPendingFree)
|
||||
|
|
|
|||
Loading…
Reference in New Issue