From 5df1cf38e3d400fe1fb175c913f759b7fa9b68a4 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 29 Oct 2019 16:24:41 +0100 Subject: [PATCH] Ensure we don't move the Listener struct around We're passing a pointer into the Listener struct to Windows API, so ensure we keep that pointer valid even when our container changes. Change-Id: I32b8de8cd959ecc7f574063451ed7238b69e7125 Reviewed-by: Simon Hausmann --- src/network/socket/qlocalserver_p.h | 9 ++++-- src/network/socket/qlocalserver_win.cpp | 38 ++++++++++++------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/network/socket/qlocalserver_p.h b/src/network/socket/qlocalserver_p.h index 92616e59ce..f331a3f10d 100644 --- a/src/network/socket/qlocalserver_p.h +++ b/src/network/socket/qlocalserver_p.h @@ -99,15 +99,18 @@ public: QMap socketMap; #elif defined(Q_OS_WIN) struct Listener { - HANDLE handle; + Listener() = default; + HANDLE handle = nullptr; OVERLAPPED overlapped; - bool connected; + bool connected = false; + private: + Q_DISABLE_COPY(Listener) }; void setError(const QString &function); bool addListener(); - QList listeners; + std::vector> listeners; HANDLE eventHandle; QWinEventNotifier *connectionEventNotifier; #else diff --git a/src/network/socket/qlocalserver_win.cpp b/src/network/socket/qlocalserver_win.cpp index 2d71a7e730..6d92ebe93a 100644 --- a/src/network/socket/qlocalserver_win.cpp +++ b/src/network/socket/qlocalserver_win.cpp @@ -62,8 +62,8 @@ bool QLocalServerPrivate::addListener() { // The object must not change its address once the // contained OVERLAPPED struct is passed to Windows. - listeners << Listener(); - Listener &listener = listeners.last(); + listeners.push_back(std::make_unique()); + auto &listener = listeners.back(); SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); @@ -175,7 +175,7 @@ bool QLocalServerPrivate::addListener() sa.lpSecurityDescriptor = pSD.data(); } - listener.handle = CreateNamedPipe( + listener->handle = CreateNamedPipe( reinterpret_cast(fullServerName.utf16()), // pipe name PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access PIPE_TYPE_BYTE | // byte type pipe @@ -187,32 +187,32 @@ bool QLocalServerPrivate::addListener() 3000, // client time-out &sa); - if (listener.handle == INVALID_HANDLE_VALUE) { + if (listener->handle == INVALID_HANDLE_VALUE) { setError(QLatin1String("QLocalServerPrivate::addListener")); - listeners.removeLast(); + listeners.pop_back(); return false; } if (worldSID) FreeSid(worldSID); - memset(&listener.overlapped, 0, sizeof(listener.overlapped)); - listener.overlapped.hEvent = eventHandle; + memset(&listener->overlapped, 0, sizeof(OVERLAPPED)); + listener->overlapped.hEvent = eventHandle; // Beware! ConnectNamedPipe will reset the eventHandle to non-signaled. // Callers of addListener must check all listeners for connections. - if (!ConnectNamedPipe(listener.handle, &listener.overlapped)) { + if (!ConnectNamedPipe(listener->handle, &listener->overlapped)) { switch (GetLastError()) { case ERROR_IO_PENDING: - listener.connected = false; + listener->connected = false; break; case ERROR_PIPE_CONNECTED: - listener.connected = true; + listener->connected = true; break; default: - CloseHandle(listener.handle); + CloseHandle(listener->handle); setError(QLatin1String("QLocalServerPrivate::addListener")); - listeners.removeLast(); + listeners.pop_back(); return false; } } else { @@ -284,12 +284,12 @@ void QLocalServerPrivate::_q_onNewConnection() // Testing shows that there is indeed absolutely no guarantee which listener gets // a client connection first, so there is no way around polling all of them. - for (int i = 0; i < listeners.size(); ) { - HANDLE handle = listeners[i].handle; - if (listeners[i].connected - || GetOverlappedResult(handle, &listeners[i].overlapped, &dummy, FALSE)) + for (size_t i = 0; i < listeners.size(); ) { + HANDLE handle = listeners[i]->handle; + if (listeners[i]->connected + || GetOverlappedResult(handle, &listeners[i]->overlapped, &dummy, FALSE)) { - listeners.removeAt(i); + listeners.erase(listeners.begin() + i); addListener(); @@ -319,8 +319,8 @@ void QLocalServerPrivate::closeServer() connectionEventNotifier->deleteLater(); connectionEventNotifier = 0; CloseHandle(eventHandle); - for (int i = 0; i < listeners.size(); ++i) - CloseHandle(listeners[i].handle); + for (size_t i = 0; i < listeners.size(); ++i) + CloseHandle(listeners[i]->handle); listeners.clear(); }