IPC: add QtIpcCommon::platformSafeKey()

This is the new implementation of how to make platform-safe native keys,
for which no past compatibility is required nor promised. Unlike when we
started in Qt 4.4, it doesn't look there are many restrictions in names
anyway.

Important differences are:
* POSIX RT: no restrictions, we prepend the necessary '/'
* System V/XSI: no restrictions, it's just a file path anyway;
  we pass absolute paths unchanged; otherwise we prepend RuntimeLocation
* Windows: no restrictions, but we do recognize Global\ and Local\
  kernel objects without munging them

The use of the RuntimeLocation may cause a warning on Unix systems
(other than Apple ones and Android) if $XDG_RUNTIME_DIR isn't set.

We do enforce the Apple 30-character limit here, otherwise you get
ENAMETOOLONG.

Change-Id: I12a088d1ae424825abd3fffd171d3a0e09e06361
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Thiago Macieira 2022-10-11 22:07:49 -07:00
parent f79b535f6b
commit 0b79f58458
2 changed files with 62 additions and 2 deletions

View File

@ -5,7 +5,7 @@
#include "qtipccommon_p.h"
#include <qcryptographichash.h>
#include <qdir.h>
#include <qstandardpaths.h>
#include <qstringconverter.h>
#include <private/qurl_p.h>
@ -153,7 +153,66 @@ QString QtIpcCommon::legacyPlatformSafeKey(const QString &key, QtIpcCommon::IpcT
}
if (!isIpcSupported(ipcType, QNativeIpcKey::Type::SystemV))
return QString();
return QDir::tempPath() + u'/' + result;
return QStandardPaths::writableLocation(QStandardPaths::TempLocation) + u'/' + result;
}
QString QtIpcCommon::platformSafeKey(const QString &key, QtIpcCommon::IpcType ipcType,
QNativeIpcKey::Type type)
{
if (key.isEmpty())
return key;
switch (type) {
case QNativeIpcKey::Type::PosixRealtime:
if (!isIpcSupported(ipcType, QNativeIpcKey::Type::PosixRealtime))
return QString();
#ifdef SHM_NAME_MAX
// The shared memory name limit on Apple platforms is very low (30
// characters), so we have to cut it down to avoid ENAMETOOLONG. We
// hope that there won't be too many collisions...
return u'/' + QStringView(key).left(SHM_NAME_MAX - 1);
#endif
return u'/' + key;
case QNativeIpcKey::Type::Windows:
if (isIpcSupported(ipcType, QNativeIpcKey::Type::Windows)) {
QStringView prefix;
QStringView payload = key;
// see https://learn.microsoft.com/en-us/windows/win32/termserv/kernel-object-namespaces
for (QStringView candidate : { u"Local\\", u"Global\\" }) {
if (!key.startsWith(candidate))
continue;
prefix = candidate;
payload = payload.sliced(prefix.size());
break;
}
QStringView mid;
switch (ipcType) {
case IpcType::SharedMemory: mid = u"shm_"; break;
case IpcType::SystemSemaphore: mid = u"sem_"; break;
}
QString result = prefix + mid + payload;
#ifdef MAX_PATH
result.truncate(MAX_PATH);
#endif
return result;
}
return QString();
case QNativeIpcKey::Type::SystemV:
break;
}
// System V
if (!isIpcSupported(ipcType, QNativeIpcKey::Type::SystemV))
return QString();
if (key.startsWith(u'/'))
return key;
QString baseDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
return baseDir + u'/' + key;
}
/*!

View File

@ -61,6 +61,7 @@ static constexpr bool isIpcSupported(IpcType ipcType, QNativeIpcKey::Type type)
Q_AUTOTEST_EXPORT QString
legacyPlatformSafeKey(const QString &key, IpcType ipcType,
QNativeIpcKey::Type type = QNativeIpcKey::legacyDefaultTypeForOs());
Q_AUTOTEST_EXPORT QString platformSafeKey(const QString &key, IpcType ipcType, QNativeIpcKey::Type type);
#ifdef Q_OS_UNIX
// Convenience function to create the file if needed