Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2025-05-13 13:18:55 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2025-05-19 09:03:36 +0200
commit62e72aa6db6af546aa6a96be027e6f0c57cd8f3e (patch)
tree7d922bee315552aa504911194133672fe11a3543 /sources/pyside6/libpyside
parent37450c89a7582c92afc6024dc52e81fba1b419c5 (diff)
Fix crash retrieving a PyObject type property via QVariant<PyObjectWrapper>
The old code registered a Shiboken converter for PyObjectWrapper by pointer conversion. This resulted in the Python to C++ converter falling back to plain pointer passthrough since it only works for SbkObjects. The C++ to Python conversion worked by coincidence for either raw PyObject * pointers used in meta call handling or pointers obtained from calling QVariant<PyObjectWrapper>.data(), but without handling reference counts. To fix this, remove the Python to C++ conversion entirely and do this manually via QVariant. Change the C++ to Python to be by value and use PyObjectWrapper. Fixes: PYSIDE-2193 Pick-to: 6.9 Change-Id: I00898894651f220d7b8fe60608e93233ef3e6493 Reviewed-by: Shyamnath Premnadh <Shyamnath.Premnadh@qt.io>
Diffstat (limited to 'sources/pyside6/libpyside')
-rw-r--r--sources/pyside6/libpyside/pysidemetafunction.cpp8
-rw-r--r--sources/pyside6/libpyside/pysideproperty.cpp25
-rw-r--r--sources/pyside6/libpyside/signalmanager.cpp34
-rw-r--r--sources/pyside6/libpyside/signalmanager.h2
4 files changed, 44 insertions, 25 deletions
diff --git a/sources/pyside6/libpyside/pysidemetafunction.cpp b/sources/pyside6/libpyside/pysidemetafunction.cpp
index 48aba3c7b..7a496c4b7 100644
--- a/sources/pyside6/libpyside/pysidemetafunction.cpp
+++ b/sources/pyside6/libpyside/pysidemetafunction.cpp
@@ -4,6 +4,8 @@
#include "pysidemetafunction.h"
#include "pysidemetafunction_p.h"
+#include <signalmanager.h>
+
#include <autodecref.h>
#include <basewrapper.h>
#include <sbkconverter.h>
@@ -12,6 +14,8 @@
#include <QtCore/qmetaobject.h>
+using namespace Qt::StringLiterals;
+
extern "C"
{
@@ -164,6 +168,10 @@ bool call(QObject *self, int methodIndex, PyObject *args, PyObject **retVal)
QString tmp;
converter.toCpp(obj, &tmp);
methValues[i] = tmp;
+ } else if (metaType.id() == PyObjectWrapper::metaTypeId()) {
+ // Manual conversion, see PyObjectWrapper converter registration
+ methValues[i] = QVariant::fromValue(PyObjectWrapper(obj.object()));
+ methArgs[i] = methValues[i].data();
} else {
converter.toCpp(obj, methArgs[i]);
}
diff --git a/sources/pyside6/libpyside/pysideproperty.cpp b/sources/pyside6/libpyside/pysideproperty.cpp
index e8ea2fa03..69d347043 100644
--- a/sources/pyside6/libpyside/pysideproperty.cpp
+++ b/sources/pyside6/libpyside/pysideproperty.cpp
@@ -6,6 +6,7 @@
#include "pysideproperty_p.h"
#include "pysidesignal.h"
#include "pysidesignal_p.h"
+#include "signalmanager.h"
#include <autodecref.h>
#include <pep384ext.h>
@@ -17,6 +18,8 @@
using namespace Shiboken;
+using namespace Qt::StringLiterals;
+
extern "C"
{
@@ -148,16 +151,20 @@ void PySidePropertyPrivate::metaCall(PyObject *source, QMetaObject::Call call, v
switch (call) {
case QMetaObject::ReadProperty: {
AutoDecRef value(getValue(source));
- auto *obValue = value.object();
- if (obValue) {
- Conversions::SpecificConverter converter(typeName);
- if (converter) {
- converter.toCpp(obValue, args[0]);
- } else {
- // PYSIDE-2160: Report an unknown type name to the caller `qtPropertyMetacall`.
- PyErr_SetObject(PyExc_StopIteration, obValue);
- }
+ if (value.isNull())
+ return;
+ if (typeName == "PyObject"_ba) {
+ // Manual conversion, see PyObjectWrapper converter registration
+ auto *pw = reinterpret_cast<PySide::PyObjectWrapper *>(args[0]);
+ pw->reset(value.object());
+ return;
+ }
+ if (Conversions::SpecificConverter converter(typeName); converter) {
+ converter.toCpp(value.object(), args[0]);
+ return;
}
+ // PYSIDE-2160: Report an unknown type name to the caller `qtPropertyMetacall`.
+ PyErr_SetObject(PyExc_StopIteration, value.object());
}
break;
diff --git a/sources/pyside6/libpyside/signalmanager.cpp b/sources/pyside6/libpyside/signalmanager.cpp
index 8b7b45546..305d2f5c3 100644
--- a/sources/pyside6/libpyside/signalmanager.cpp
+++ b/sources/pyside6/libpyside/signalmanager.cpp
@@ -24,6 +24,7 @@
#include <QtCore/qcoreevent.h>
#include <QtCore/qdebug.h>
#include <QtCore/qhash.h>
+#include <QtCore/qmetatype.h>
#include <QtCore/qscopedpointer.h>
#include <climits>
@@ -38,6 +39,8 @@ using namespace Qt::StringLiterals;
static PyObject *metaObjectAttr = nullptr;
+static int pyObjectWrapperMetaTypeId = QMetaType::UnknownType;
+
static void destroyMetaObject(PyObject *obj)
{
void *ptr = PyCapsule_GetPointer(obj, nullptr);
@@ -169,6 +172,10 @@ PyObjectWrapper::operator PyObject *() const
return m_me;
}
+int PyObjectWrapper::metaTypeId()
+{
+ return pyObjectWrapperMetaTypeId;
+}
int PyObjectWrapper::toInt() const
{
@@ -273,19 +280,11 @@ struct SignalManagerPrivate
SignalManager::QmlMetaCallErrorHandler
SignalManagerPrivate::m_qmlMetaCallErrorHandler = nullptr;
-static void PyObject_PythonToCpp_PyObject_PTR(PyObject *pyIn, void *cppOut)
-{
- *reinterpret_cast<PyObject **>(cppOut) = pyIn;
-}
-static PythonToCppFunc is_PyObject_PythonToCpp_PyObject_PTR_Convertible(PyObject * /* pyIn */)
-{
- return PyObject_PythonToCpp_PyObject_PTR;
-}
-static PyObject *PyObject_PTR_CppToPython_PyObject(const void *cppIn)
+static PyObject *CopyCppToPythonPyObject(const void *cppIn)
{
- auto *pyOut = reinterpret_cast<PyObject *>(const_cast<void *>(cppIn));
- if (pyOut)
- Py_INCREF(pyOut);
+ const auto *wrapper = reinterpret_cast<const PyObjectWrapper *>(cppIn);
+ PyObject *pyOut = *wrapper;
+ Py_XINCREF(pyOut);
return pyOut;
}
@@ -295,13 +294,16 @@ void SignalManager::init()
using namespace Shiboken;
// Register PyObject type to use in queued signal and slot connections
- qRegisterMetaType<PyObjectWrapper>("PyObject");
+ pyObjectWrapperMetaTypeId = qRegisterMetaType<PyObjectWrapper>("PyObject");
// Register QVariant(enum) conversion to QVariant(int)
QMetaType::registerConverter<PyObjectWrapper, int>(&PyObjectWrapper::toInt);
- SbkConverter *converter = Shiboken::Conversions::createConverter(&PyBaseObject_Type, nullptr);
- Shiboken::Conversions::setCppPointerToPythonFunction(converter, PyObject_PTR_CppToPython_PyObject);
- Shiboken::Conversions::setPythonToCppPointerFunctions(converter, PyObject_PythonToCpp_PyObject_PTR, is_PyObject_PythonToCpp_PyObject_PTR_Convertible);
+ // Register a shiboken converter for PyObjectWrapper->Python (value conversion).
+ // Python->PyObjectWrapper is not registered since the converters do not work for
+ // non-SbkObject types (falling back to plain pointer pass through).
+ // This conversion needs to be done manually via QVariant.
+ SbkConverter *converter = Shiboken::Conversions::createConverter(&PyBaseObject_Type,
+ CopyCppToPythonPyObject);
Shiboken::Conversions::registerConverterName(converter, "PyObject");
Shiboken::Conversions::registerConverterName(converter, "object");
Shiboken::Conversions::registerConverterName(converter, "PyObjectWrapper");
diff --git a/sources/pyside6/libpyside/signalmanager.h b/sources/pyside6/libpyside/signalmanager.h
index 7c2977239..9fe56efc2 100644
--- a/sources/pyside6/libpyside/signalmanager.h
+++ b/sources/pyside6/libpyside/signalmanager.h
@@ -44,6 +44,8 @@ public:
// The proper fix would be to associate PyObjectWrapper to the corresponding C++ Enum.
int toInt() const;
+ static int metaTypeId();
+
private:
PyObject* m_me;
};