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-13 12:08:16 +0000
commitaf1bdd8447771728321984f87447187f0284db6b (patch)
treefd51376cba46d0a80cbc124c2db9d8e1f2ac1ff4 /sources
parent35285e0c88c0652e602a91e03c4a2bf6b493d7c6 (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')
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang.cpp8
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetalang.h1
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp52
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.h3
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);