From 7a65abb50eb638de445e24c2746d7f90c1b89f06 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Thu, 8 Aug 2024 11:40:03 +0200 Subject: [PATCH] Don't increase the refcount if qobject_cast failed Follow the dynamicCast/dynamic_pointer_cast implementation for objectCast/object_pointer_cast since a qobject_cast can fail just like a dynamic dast. Also see: https://eel.is/c++draft/util.smartptr.shared.cast#6.2 See commit this commit from 2013 for more historical context: a094bf5a893c3cccffff10c1420bfbe3a3c02a7c Pick-to: 6.8 6.7 6.5 Change-Id: I9a54af55a7a1cf106cace52e9cf3bc103ae0bd42 Reviewed-by: Thiago Macieira --- src/corelib/tools/qsharedpointer_impl.h | 6 +++++- .../tools/qsharedpointer/tst_qsharedpointer.cpp | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 5982afd7a9b..9816c6198fc 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -901,6 +901,8 @@ template Q_INLINE_TEMPLATE QSharedPointer qSharedPointerObjectCast(const QSharedPointer &src) { X *ptr = qobject_cast(src.data()); + if (!ptr) + return QSharedPointer(); return QtSharedPointer::copyAndSetPointer(ptr, src); } template @@ -943,7 +945,9 @@ template std::shared_ptr qobject_pointer_cast(const std::shared_ptr &src) { using element_type = typename std::shared_ptr::element_type; - return std::shared_ptr(src, qobject_cast(src.get())); + if (auto ptr = qobject_cast(src.get())) + return std::shared_ptr(src, ptr); + return std::shared_ptr(); } template diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp index 056ce4281cf..1579d04bdf0 100644 --- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp @@ -60,6 +60,7 @@ private slots: void weakQObjectFromSharedPointer(); void objectCast(); void objectCastStdSharedPtr(); + void objectCastFailureNoLeak(); void differentPointers(); void virtualBaseDifferentPointers(); void virtualBaseWeakPointerConversions(); @@ -1109,6 +1110,21 @@ void tst_QSharedPointer::objectCast() safetyCheck(); } +void tst_QSharedPointer::objectCastFailureNoLeak() +{ + // verify that a failing object cast doesn't keep the original object alive + auto ptr = QSharedPointer::create(); + auto qptr = QPointer(ptr.data()); + auto ptr2 = ptr.objectCast(); + + QVERIFY(ptr); + QVERIFY(qptr); + QVERIFY(!ptr2); + + ptr.reset(); + QVERIFY(!ptr); + QVERIFY(!qptr); +} void tst_QSharedPointer::objectCastStdSharedPtr() {