aboutsummaryrefslogtreecommitdiffstats
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 12:27:27 +0200
commit66f60a96e3d84c6a4ea897726632dce48482104b (patch)
tree7c980330f5d6e6b2c4fc632443f35935992742db
parentc226d281975e933c69e56da7a54e9f2b8c7107b6 (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>
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang.cpp8
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang.h1
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp53
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.h3
4 files changed, 52 insertions, 13 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
index abc939dcf..47249b648 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp
@@ -42,6 +42,8 @@
#include <QtCore/QDebug>
+#include <algorithm>
+
bool function_sorter(const AbstractMetaFunctionCPtr &a, const AbstractMetaFunctionCPtr &b)
{
return a->signature() < b->signature();
@@ -286,6 +288,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 3626ba469..5a155c6fc 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetalang.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetalang.h
@@ -123,6 +123,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 9eec438a6..2dd13c1c6 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -765,6 +765,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(),
@@ -5313,6 +5316,12 @@ QString CppGenerator::getInitFunctionName(const GeneratorContext &context) const
: getFilteredCppSignatureString(context.preciseType().cppSignature());
}
+QString CppGenerator::getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClass *metaClass) const
+{
+ return QLatin1String("init_") + getSimpleClassInitFunctionName(metaClass)
+ + QLatin1String("StaticFields");
+}
+
void CppGenerator::writeSignatureStrings(TextStream &s,
const QString &signatures,
const QString &arrayName,
@@ -5503,19 +5512,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';
@@ -5546,6 +5542,23 @@ void CppGenerator::writeClassRegister(TextStream &s,
s << outdent << "}\n";
}
+void CppGenerator::writeStaticFieldInitialization(TextStream &s,
+ const AbstractMetaClass *metaClass) const
+{
+ 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
{
const AbstractMetaClass *metaClass = context.metaClass();
@@ -5937,11 +5950,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);
+ }
}
}
@@ -6232,6 +6251,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 97811c946..26958e6a4 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.h
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.h
@@ -278,6 +278,7 @@ private:
QString getInitFunctionName(const GeneratorContext &context) const;
QString getSimpleClassInitFunctionName(const AbstractMetaClass *metaClass) const;
+ QString getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClass *metaClass) const;
void writeSignatureStrings(TextStream &s, const QString &signatures,
const QString &arrayName,
@@ -286,6 +287,8 @@ private:
const AbstractMetaClass *metaClass,
const GeneratorContext &classContext,
const QString &signatures) const;
+ void writeStaticFieldInitialization(TextStream &s,
+ const AbstractMetaClass *metaClass) const;
void writeClassDefinition(TextStream &s,
const AbstractMetaClass *metaClass,
const GeneratorContext &classContext);