diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2021-04-09 14:41:40 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2021-04-13 12:08:16 +0000 |
commit | af1bdd8447771728321984f87447187f0284db6b (patch) | |
tree | fd51376cba46d0a80cbc124c2db9d8e1f2ac1ff4 /sources | |
parent | 35285e0c88c0652e602a91e03c4a2bf6b493d7c6 (diff) |
shiboken6: Prevent crashes when registering static fields
Registering static fields invokes converters, which
can cause crashes for uninitialized types (see also
2ac1870053370e017567ae53e62cd1155a01c88f). To solve
this problem, move the static field initialization
to the end of the module initialization function
to ensure all converters are available.
Pick-to: 5.15 6.0
Fixes: PYSIDE-1529
Change-Id: If40c6faf049077db8afcdee2069f4441c21beaa4
Reviewed-by: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'sources')
4 files changed, 51 insertions, 13 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp index 6da087075..69f48ca91 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp @@ -43,6 +43,8 @@ #include <QtCore/QDebug> +#include <algorithm> + bool function_sorter(const AbstractMetaFunctionCPtr &a, const AbstractMetaFunctionCPtr &b) { return a->signature() < b->signature(); @@ -327,6 +329,12 @@ void AbstractMetaClass::addField(const AbstractMetaField &field) d->m_fields << field; } +bool AbstractMetaClass::hasStaticFields() const +{ + return std::any_of(d->m_fields.cbegin(), d->m_fields.cend(), + [](const AbstractMetaField &f) { return f.isStatic(); }); +} + void AbstractMetaClass::sortFunctions() { std::sort(d->m_functions.begin(), d->m_functions.end(), function_sorter); diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.h b/sources/shiboken6/ApiExtractor/abstractmetalang.h index eab7969a6..f83062dd7 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.h @@ -174,6 +174,7 @@ public: AbstractMetaFieldList &fields(); void setFields(const AbstractMetaFieldList &fields); void addField(const AbstractMetaField &field); + bool hasStaticFields() const; std::optional<AbstractMetaField> findField(const QString &name) const; diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index ed16deca8..a5d38b87b 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -764,6 +764,9 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon writeConverterFunctions(s, metaClass, classContext); writeClassRegister(s, metaClass, classContext, signatureStream); + if (metaClass->hasStaticFields()) + writeStaticFieldInitialization(s, metaClass); + // class inject-code native/end if (!metaClass->typeEntry()->codeSnips().isEmpty()) { writeClassCodeSnips(s, metaClass->typeEntry()->codeSnips(), @@ -5319,6 +5322,12 @@ QString CppGenerator::getSimpleClassInitFunctionName(const AbstractMetaClass *me return initFunctionName; } +QString CppGenerator::getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClass *metaClass) +{ + return QLatin1String("init_") + getSimpleClassInitFunctionName(metaClass) + + QLatin1String("StaticFields"); +} + QString CppGenerator::getInitFunctionName(const GeneratorContext &context) { return !context.forSmartPointer() @@ -5516,19 +5525,6 @@ void CppGenerator::writeClassRegister(TextStream &s, if (metaClass->hasSignals()) writeSignalInitialization(s, metaClass); - // Write static fields - const AbstractMetaFieldList &fields = metaClass->fields(); - for (const AbstractMetaField &field : fields) { - if (!field.isStatic()) - continue; - s << "PyDict_SetItemString(reinterpret_cast<PyTypeObject *>(" - << cpythonTypeName(metaClass) << ")->tp_dict, \"" - << field.name() << "\", "; - writeToPythonConversion(s, field.type(), metaClass, field.qualifiedCppName()); - s << ");\n"; - } - s << '\n'; - // class inject-code target/end if (!classTypeEntry->codeSnips().isEmpty()) { s << '\n'; @@ -5559,6 +5555,22 @@ void CppGenerator::writeClassRegister(TextStream &s, s << outdent << "}\n"; } +void CppGenerator::writeStaticFieldInitialization(TextStream &s, const AbstractMetaClass *metaClass) +{ + s << "\nvoid " << getSimpleClassStaticFieldsInitFunctionName(metaClass) + << "()\n{\n" << indent << "auto dict = reinterpret_cast<PyTypeObject *>(" + << cpythonTypeName(metaClass) << ")->tp_dict;\n"; + for (const AbstractMetaField &field : metaClass->fields()) { + if (field.isStatic()) { + s << "PyDict_SetItemString(dict, \"" << field.name() + << "\",\n "; + writeToPythonConversion(s, field.type(), metaClass, field.qualifiedCppName()); + s << ");\n"; + } + } + s << '\n' << outdent << "}\n"; +} + void CppGenerator::writeInitQtMetaTypeFunctionBody(TextStream &s, const GeneratorContext &context) { const AbstractMetaClass *metaClass = context.metaClass(); @@ -5952,11 +5964,17 @@ bool CppGenerator::finishGeneration() writeMethodDefinition(s_globalFunctionDef, overloads); } + AbstractMetaClassCList classesWithStaticFields; for (auto cls : api().classes()){ if (shouldGenerate(cls)) { writeInitFunc(s_classInitDecl, s_classPythonDefines, getSimpleClassInitFunctionName(cls), cls->typeEntry()->targetLangEnclosingEntry()); + if (cls->hasStaticFields()) { + s_classInitDecl << "void " + << getSimpleClassStaticFieldsInitFunctionName(cls) << "();\n"; + classesWithStaticFields.append(cls); + } } } @@ -6247,6 +6265,14 @@ bool CppGenerator::finishGeneration() s << "Shiboken::Module::registerTypes(module, " << cppApiVariableName() << ");\n"; s << "Shiboken::Module::registerTypeConverters(module, " << convertersVariableName() << ");\n"; + // Static fields are registered last since they may use converter functions + // of the previously registered types (PYSIDE-1529). + if (!classesWithStaticFields.isEmpty()) { + s << "\n// Static field initialization\n"; + for (auto cls : qAsConst(classesWithStaticFields)) + s << getSimpleClassStaticFieldsInitFunctionName(cls) << "();\n"; + } + s << "\nif (PyErr_Occurred()) {\n" << indent << "PyErr_Print();\n" << "Py_FatalError(\"can't initialize module " << moduleName() << "\");\n" diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h index 3e230fa11..745d60dff 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.h +++ b/sources/shiboken6/generator/shiboken/cppgenerator.h @@ -279,6 +279,7 @@ private: static QString getInitFunctionName(const GeneratorContext &context) ; static QString getSimpleClassInitFunctionName(const AbstractMetaClass *metaClass) ; + static QString getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClass *metaClass); static void writeSignatureStrings(TextStream &s, const QString &signatures, const QString &arrayName, @@ -287,6 +288,8 @@ private: const AbstractMetaClass *metaClass, const GeneratorContext &classContext, const QString &signatures) const; + static void writeStaticFieldInitialization(TextStream &s, + const AbstractMetaClass *metaClass); void writeClassDefinition(TextStream &s, const AbstractMetaClass *metaClass, const GeneratorContext &classContext); |