aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2021-04-09 14:41:40 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2021-04-15 14:36:59 +0200
commit49c115b88d9175c7c160e81d11450c6d42029b5f (patch)
tree9c86a0906740d7397bdbd1d685b6185938445da1 /sources
parentd47736aef4794c4eb81199d71f82ec1ebaced6cf (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. Fixes: PYSIDE-1529 Change-Id: If40c6faf049077db8afcdee2069f4441c21beaa4 Reviewed-by: Renato Araujo Oliveira Filho <renato.araujo@kdab.com> Reviewed-by: Christian Tismer <tismer@stackless.com> (cherry picked from commit af1bdd8447771728321984f87447187f0284db6b) Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'sources')
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp6
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h2
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp59
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.h3
4 files changed, 58 insertions, 12 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
index 97bfd8f1b..06d5af14c 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
@@ -2116,6 +2116,12 @@ AbstractMetaField *AbstractMetaClass::findField(const QString &name) const
return AbstractMetaField::find(m_fields, name);
}
+bool AbstractMetaClass::hasStaticFields() const
+{
+ return std::any_of(m_fields.cbegin(), m_fields.cend(),
+ [](const AbstractMetaField *f) { return f->isStatic(); });
+}
+
AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName)
{
if (AbstractMetaEnum *e = findByName(m_enums, enumName))
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h
index 52adebf94..9d0facd7d 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang.h
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h
@@ -1417,6 +1417,8 @@ public:
AbstractMetaField *findField(const QString &name) const;
+ bool hasStaticFields() const;
+
const AbstractMetaEnumList &enums() const { return m_enums; }
void setEnums(const AbstractMetaEnumList &enums)
{
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index 4f3bd2d0a..f299ba428 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -755,6 +755,9 @@ void CppGenerator::generateClass(QTextStream &s, const GeneratorContext &classCo
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(),
@@ -5274,6 +5277,12 @@ QString CppGenerator::getSimpleClassInitFunctionName(const AbstractMetaClass *me
return initFunctionName;
}
+QString CppGenerator::getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClass *metaClass) const
+{
+ return QLatin1String("init_") + getSimpleClassInitFunctionName(metaClass)
+ + QLatin1String("StaticFields");
+}
+
QString CppGenerator::getInitFunctionName(const GeneratorContext &context) const
{
return !context.forSmartPointer()
@@ -5476,18 +5485,6 @@ void CppGenerator::writeClassRegister(QTextStream &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 << INDENT << QLatin1String("PyDict_SetItemString(reinterpret_cast<PyTypeObject *>(") + cpythonTypeName(metaClass) + QLatin1String(")->tp_dict, \"");
- s << field->name() << "\", ";
- writeToPythonConversion(s, field->type(), metaClass, metaClass->qualifiedCppName() + QLatin1String("::") + field->name());
- s << ");\n";
- }
- s << Qt::endl;
-
// class inject-code target/end
if (!classTypeEntry->codeSnips().isEmpty()) {
s << Qt::endl;
@@ -5517,6 +5514,29 @@ void CppGenerator::writeClassRegister(QTextStream &s,
s << "}\n";
}
+void CppGenerator::writeStaticFieldInitialization(QTextStream &s,
+ const AbstractMetaClass *metaClass)
+{
+ s << "\nvoid " << getSimpleClassStaticFieldsInitFunctionName(metaClass)
+ << "()\n{\n" << INDENT << "auto dict = reinterpret_cast<PyTypeObject *>("
+ << cpythonTypeName(metaClass) << ")->tp_dict;\n";
+ const auto &fields = metaClass->fields();
+ for (const AbstractMetaField *field : fields) {
+ if (field->isStatic()) {
+ QString cppName = field->originalName();
+ if (cppName.isEmpty())
+ cppName = field->name();
+ const QString name = field->enclosingClass()->qualifiedCppName()
+ + QLatin1String("::") + cppName;
+ s << INDENT << "PyDict_SetItemString(dict, \"" << field->name()
+ << "\",\n" << INDENT << " ";
+ writeToPythonConversion(s, field->type(), metaClass, name);
+ s << ");\n";
+ }
+ }
+ s << "\n}\n";
+}
+
void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, const GeneratorContext &context) const
{
const AbstractMetaClass *metaClass = context.metaClass();
@@ -5927,11 +5947,18 @@ bool CppGenerator::finishGeneration()
}
const AbstractMetaClassList lst = classesTopologicalSorted(additionalDependencies);
+ QVector<const AbstractMetaClass *> classesWithStaticFields;
+
for (const AbstractMetaClass *cls : lst){
if (shouldGenerate(cls)) {
writeInitFunc(s_classInitDecl, s_classPythonDefines, INDENT,
getSimpleClassInitFunctionName(cls),
cls->typeEntry()->targetLangEnclosingEntry());
+ if (cls->hasStaticFields()) {
+ s_classInitDecl << "void "
+ << getSimpleClassStaticFieldsInitFunctionName(cls) << "();\n";
+ classesWithStaticFields.append(cls);
+ }
}
}
@@ -6233,6 +6260,14 @@ bool CppGenerator::finishGeneration()
s << INDENT << "Shiboken::Module::registerTypes(module, " << cppApiVariableName() << ");\n";
s << INDENT << "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 << '\n' << INDENT << "if (PyErr_Occurred()) {\n" << indent(INDENT)
<< INDENT << "PyErr_Print();\n"
<< INDENT << "Py_FatalError(\"can't initialize module " << moduleName() << "\");\n"
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.h b/sources/shiboken2/generator/shiboken2/cppgenerator.h
index 79b8774a9..cc03c86e0 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.h
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.h
@@ -250,6 +250,7 @@ private:
QString getInitFunctionName(const GeneratorContext &context) const;
QString getSimpleClassInitFunctionName(const AbstractMetaClass *metaClass) const;
+ QString getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClass *metaClass) const;
void writeSignatureStrings(QTextStream &s, QTextStream &signatureStream,
const QString &arrayName,
@@ -258,6 +259,8 @@ private:
const AbstractMetaClass *metaClass,
const GeneratorContext &classContext,
QTextStream &signatureStream);
+ void writeStaticFieldInitialization(QTextStream &s,
+ const AbstractMetaClass *metaClass);
void writeClassDefinition(QTextStream &s,
const AbstractMetaClass *metaClass,
const GeneratorContext &classContext);