Fix UB in tst_QObject::disconnectDoesNotLeakFunctor()
If CountedStruct is passed a GetSenderObject object, it will attempt to call a member on it from within its own destructor. That works usually quite well, but in this test case, which tests for function object leaks when a connection is torn down because the sender object is destroyed, the destruction of the CountedStruct happens when all connections are severed in ~QObject. At that point, what used to be a GetSenderObject instance no longer is one and the call into one of its member functions invokes undefined behavior. Fix by making QObject::sender() public by a using declaration instead of a wrapper function. Found by UBSan: tests/auto/corelib/kernel/qobject/tst_qobject.cpp:6007:104: runtime error: member call on address 0x7ffc6e7538b0 which does not point to an object of type 'GetSenderObject' 0x7ffc6e7538b0: note: object is of type 'QObject' Change-Id: Ia973140037b3c1b5a670a8a3949d09b956f40349 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
parent
889fcfbf2b
commit
1e2b42523f
@ -5987,7 +5987,7 @@ class GetSenderObject : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
QObject *accessSender() { return sender(); }
|
using QObject::sender; // make public
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void triggerSignal() { Q_EMIT aSignal(); }
|
void triggerSignal() { Q_EMIT aSignal(); }
|
||||||
@ -6003,8 +6003,8 @@ struct CountedStruct
|
|||||||
CountedStruct(GetSenderObject *sender) : sender(sender) { ++countedStructObjectsCount; }
|
CountedStruct(GetSenderObject *sender) : sender(sender) { ++countedStructObjectsCount; }
|
||||||
CountedStruct(const CountedStruct &o) : sender(o.sender) { ++countedStructObjectsCount; }
|
CountedStruct(const CountedStruct &o) : sender(o.sender) { ++countedStructObjectsCount; }
|
||||||
CountedStruct &operator=(const CountedStruct &) { return *this; }
|
CountedStruct &operator=(const CountedStruct &) { return *this; }
|
||||||
// accessSender here allows us to check if there's a deadlock
|
// calling sender() here allows us to check if there's a deadlock
|
||||||
~CountedStruct() { --countedStructObjectsCount; if (sender != Q_NULLPTR) (void)sender->accessSender(); }
|
~CountedStruct() { --countedStructObjectsCount; if (sender) (void)sender->sender(); }
|
||||||
void operator()() const { }
|
void operator()() const { }
|
||||||
|
|
||||||
GetSenderObject *sender;
|
GetSenderObject *sender;
|
||||||
|
Loading…
Reference in New Issue
Block a user