diff options
author | Marc Mutz <marc.mutz@qt.io> | 2022-02-11 09:12:49 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-02-13 19:53:26 +0000 |
commit | b0b3e9a04747246cd381afdcd28f58d4a09068dc (patch) | |
tree | 088c3fe1745a4afef6c186fbdd07e1fec478a577 | |
parent | 0e97205fbd0326c0dfa22de174117ba157595255 (diff) | |
download | qtbase-b0b3e9a04747246cd381afdcd28f58d4a09068dc.tar.gz |
QDesktopServices: fix UB (data race on handlers)
The handlerDestroyed() function is connected to the handler QObject's
destroyed() signal and removes all entries from the registry for which
the destroyed object was listed as the handler.
While handlerDestroyed() is always executed in the context of the
thread owning QOpenUrlHandlerRegistry-as-a-QObject, the documentation
explicitly states that "the handler will always be called from within
the same thread that calls QDesktopServices::openUrl()", implying that
calling openUrl() from a non-GUI thread is supported. The presence of
the mutex also indicates that this should work.
But then the unprotected access to the handlers variable in
handlerDestroyed() is a data race, because nothing prevents a handler
object from being destroyed concurrent to an openUrl() call.
Fix by locking the mutex.
Fixes: QTBUG-100777
Change-Id: I9ef857efa609b4d16ee21063ccccd316e119576b
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
(cherry picked from commit 42e13b7c61693ca95e119106d4f6dbd2bcf2308d)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/gui/util/qdesktopservices.cpp | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp index 8f1b035483..be63b3768a 100644 --- a/src/gui/util/qdesktopservices.cpp +++ b/src/gui/util/qdesktopservices.cpp @@ -54,6 +54,8 @@ #include <qpa/qplatformintegration.h> #include <qdir.h> +#include <QtCore/private/qlocking_p.h> + QT_BEGIN_NAMESPACE class QOpenUrlHandlerRegistry : public QObject @@ -81,6 +83,7 @@ Q_GLOBAL_STATIC(QOpenUrlHandlerRegistry, handlerRegistry) void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler) { + const auto lock = qt_scoped_lock(mutex); HandlerHash::Iterator it = handlers.begin(); while (it != handlers.end()) { if (it->receiver == handler) { |