summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2022-08-03 19:23:28 +0200
committerMarc Mutz <marc.mutz@qt.io>2022-08-06 14:21:46 +0000
commit5ff71637968c70f138d8ea6cc24e61c1608f2187 (patch)
tree4b4f605969497961e70ad311b2ebed3d0b4060e3
parent5b62970b9441717670a1756b858c500004dfdfe0 (diff)
qputenv: port to QByteArrayView
The vast majority of in-tree users pass simple and short C string literals as the value. By porting to QByteArrayView, we document that we'll accept non-NUL-terminated data, and do the NUL-termination internally, using SSO'ed std::string, saving memory allocations in the common case of short strings. I didn't bother to check which direction std::string takes for nullptrs these days (there was a change accepted in that area for C++20 or 23), so play it safe and protect against them. Follow-up to Task-number: QTBUG-105302 Change-Id: I2369acc62f1d5cbc26135396cfe0602d8c75300c Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io> Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
-rw-r--r--src/corelib/compat/removed_api.cpp7
-rw-r--r--src/corelib/global/qenvironmentvariables.cpp25
-rw-r--r--src/corelib/global/qenvironmentvariables.h6
-rw-r--r--src/gui/opengl/platform/unix/qglxconvenience.cpp2
-rw-r--r--tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp2
-rw-r--r--tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp8
-rw-r--r--tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp4
-rw-r--r--tests/auto/gui/kernel/qhighdpi/tst_qhighdpi.cpp2
-rw-r--r--tests/auto/network/access/http2/tst_http2.cpp10
-rw-r--r--tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp2
-rw-r--r--tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp2
-rw-r--r--tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp2
12 files changed, 43 insertions, 29 deletions
diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp
index 2b864ad41f..aa1a496f0f 100644
--- a/src/corelib/compat/removed_api.cpp
+++ b/src/corelib/compat/removed_api.cpp
@@ -285,6 +285,13 @@ QT_WARNING_POP
#if QT_CORE_REMOVED_SINCE(6, 5)
+#include "qenvironmentvariables.h"
+
+bool qputenv(const char *varName, const QByteArray &value)
+{
+ return qputenv(varName, qToByteArrayViewIgnoringNull(value));
+}
+
#include "qmetatype.h"
int QMetaType::idHelper() const
diff --git a/src/corelib/global/qenvironmentvariables.cpp b/src/corelib/global/qenvironmentvariables.cpp
index d3d963e52e..4860913327 100644
--- a/src/corelib/global/qenvironmentvariables.cpp
+++ b/src/corelib/global/qenvironmentvariables.cpp
@@ -243,6 +243,7 @@ bool qEnvironmentVariableIsSet(const char *varName) noexcept
}
/*!
+ \fn bool qputenv(const char *varName, QByteArrayView value)
\relates <QEnvironmentVariables>
This function sets the \a value of the environment variable named
@@ -258,30 +259,30 @@ bool qEnvironmentVariableIsSet(const char *varName) noexcept
uses the replacement function in VC, and calls the standard C
library's implementation on all other platforms.
+ \note In Qt versions prior to 6.5, the \a value argument was QByteArray,
+ not QByteArrayView.
+
\sa qgetenv(), qEnvironmentVariable()
*/
-bool qputenv(const char *varName, const QByteArray &value)
+bool qputenv(const char *varName, QByteArrayView raw)
{
- // protect against non-NUL-terminated QByteArrays:
- if (!const_cast<QByteArray&>(value).data_ptr()->isMutable()) {
- QByteArray copy(value);
- copy.reserve(copy.size() + 1); // ensures NUL termination (and isMutable() even for size==0
- // (unlike detach()) to avoid infinite recursion)
- return qputenv(varName, copy);
- }
+ auto protect = [](const char *str) { return str ? str : ""; };
+
+ std::string value{protect(raw.data()), size_t(raw.size())}; // NUL-terminates w/SSO
#if defined(Q_CC_MSVC)
const auto locker = qt_scoped_lock(environmentMutex);
- return _putenv_s(varName, value.constData()) == 0;
+ return _putenv_s(varName, value.data()) == 0;
#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_HAIKU)
// POSIX.1-2001 has setenv
const auto locker = qt_scoped_lock(environmentMutex);
- return setenv(varName, value.constData(), true) == 0;
+ return setenv(varName, value.data(), true) == 0;
#else
- QByteArray buffer(varName);
+ std::string buffer;
+ buffer += protect(varName);
buffer += '=';
buffer += value;
- char *envVar = qstrdup(buffer.constData());
+ char *envVar = qstrdup(buffer.data());
int result = [&] {
const auto locker = qt_scoped_lock(environmentMutex);
return putenv(envVar);
diff --git a/src/corelib/global/qenvironmentvariables.h b/src/corelib/global/qenvironmentvariables.h
index cde51c9ba1..78fea255d3 100644
--- a/src/corelib/global/qenvironmentvariables.h
+++ b/src/corelib/global/qenvironmentvariables.h
@@ -5,6 +5,7 @@
#define QENVIRONMENTVARIABLES_H
#include <QtCore/qglobal.h>
+#include <QtCore/qtdeprecationmarkers.h>
#if 0
#pragma qt_class(QEnvironmentVariables)
@@ -14,11 +15,16 @@
QT_BEGIN_NAMESPACE
class QByteArray;
+class QByteArrayView;
+
Q_CORE_EXPORT QByteArray qgetenv(const char *varName);
// need it as two functions because QString is only forward-declared here
Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName);
Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName, const QString &defaultValue);
+#if QT_CORE_REMOVED_SINCE(6, 5)
Q_CORE_EXPORT bool qputenv(const char *varName, const QByteArray &value);
+#endif
+Q_CORE_EXPORT bool qputenv(const char *varName, QByteArrayView value);
Q_CORE_EXPORT bool qunsetenv(const char *varName);
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept;
diff --git a/src/gui/opengl/platform/unix/qglxconvenience.cpp b/src/gui/opengl/platform/unix/qglxconvenience.cpp
index a756caf343..ce70818042 100644
--- a/src/gui/opengl/platform/unix/qglxconvenience.cpp
+++ b/src/gui/opengl/platform/unix/qglxconvenience.cpp
@@ -124,7 +124,7 @@ struct QXcbSoftwareOpenGLEnforcer {
}
if (forceSoftwareOpenGL)
- qputenv("LIBGL_ALWAYS_SOFTWARE", QByteArrayLiteral("1"));
+ qputenv("LIBGL_ALWAYS_SOFTWARE", "1");
}
~QXcbSoftwareOpenGLEnforcer() {
diff --git a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
index a0a9bb940e..3ba6de20a9 100644
--- a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
+++ b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
@@ -181,7 +181,7 @@ private slots:
void initTestCase()
{
qputenv("XDG_CONFIG_DIRS", "/does/not/exist");
- qputenv("QT_MESSAGE_PATTERN", QByteArray("%{category}: %{type},%{message}"));
+ qputenv("QT_MESSAGE_PATTERN", "%{category}: %{type},%{message}");
oldMessageHandler = qInstallMessageHandler(myCustomMessageHandler);
// Create configuration
_config = new Configuration();
diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
index 2c0500eec9..b2bb14180e 100644
--- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
+++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
@@ -64,10 +64,10 @@ private:
qputenv("XDG_DATA_DIRS", QFile::encodeName(m_globalAppDir));
}
void setDefaultLocations() {
- qputenv("XDG_CONFIG_HOME", QByteArray());
- qputenv("XDG_CONFIG_DIRS", QByteArray());
- qputenv("XDG_DATA_HOME", QByteArray());
- qputenv("XDG_DATA_DIRS", QByteArray());
+ qputenv("XDG_CONFIG_HOME", nullptr);
+ qputenv("XDG_CONFIG_DIRS", nullptr);
+ qputenv("XDG_DATA_HOME", nullptr);
+ qputenv("XDG_DATA_DIRS", nullptr);
}
#endif
diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
index 6bec1969ab..e9d2064503 100644
--- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
+++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
@@ -153,7 +153,7 @@ private:
{ reset(zone); }
void reset(const QByteArray &zone)
{
- qputenv("TZ", zone.constData());
+ qputenv("TZ", zone);
qTzSet();
}
~TimeZoneRollback()
@@ -161,7 +161,7 @@ private:
if (prior.isNull())
qunsetenv("TZ");
else
- qputenv("TZ", prior.constData());
+ qputenv("TZ", prior);
qTzSet();
}
};
diff --git a/tests/auto/gui/kernel/qhighdpi/tst_qhighdpi.cpp b/tests/auto/gui/kernel/qhighdpi/tst_qhighdpi.cpp
index f221c9db90..2196724f41 100644
--- a/tests/auto/gui/kernel/qhighdpi/tst_qhighdpi.cpp
+++ b/tests/auto/gui/kernel/qhighdpi/tst_qhighdpi.cpp
@@ -270,7 +270,7 @@ void tst_QHighDpi::screenDpiChange()
void tst_QHighDpi::environment_QT_SCALE_FACTOR()
{
qreal factor = 3.1415;
- qputenv("QT_SCALE_FACTOR", QByteArray::number(factor));
+ qputenv("QT_SCALE_FACTOR", std::to_string(factor));
QList<qreal> dpiValues { 96, 144, 192 };
std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues));
diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp
index 8207f65dcd..bb2437c7f5 100644
--- a/tests/auto/network/access/http2/tst_http2.cpp
+++ b/tests/auto/network/access/http2/tst_http2.cpp
@@ -238,7 +238,7 @@ void tst_Http2::singleRequest()
// we have to use TLS sockets (== private key) and thus suppress a
// keychain UI asking for permission to use a private key.
// Our CI has this, but somebody testing locally - will have a problem.
- qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", QByteArray("1"));
+ qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", "1");
auto envRollback = qScopeGuard([](){
qunsetenv("QT_SSL_USE_TEMPORARY_KEYCHAIN");
});
@@ -630,7 +630,7 @@ void tst_Http2::connectToHost()
// we have to use TLS sockets (== private key) and thus suppress a
// keychain UI asking for permission to use a private key.
// Our CI has this, but somebody testing locally - will have a problem.
- qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", QByteArray("1"));
+ qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", "1");
auto envRollback = qScopeGuard([](){
qunsetenv("QT_SSL_USE_TEMPORARY_KEYCHAIN");
});
@@ -728,7 +728,7 @@ void tst_Http2::maxFrameSize()
// we have to use TLS sockets (== private key) and thus suppress a
// keychain UI asking for permission to use a private key.
// Our CI has this, but somebody testing locally - will have a problem.
- qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", QByteArray("1"));
+ qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", "1");
auto envRollback = qScopeGuard([](){
qunsetenv("QT_SSL_USE_TEMPORARY_KEYCHAIN");
});
@@ -893,7 +893,7 @@ void tst_Http2::moreActivitySignals()
// we have to use TLS sockets (== private key) and thus suppress a
// keychain UI asking for permission to use a private key.
// Our CI has this, but somebody testing locally - will have a problem.
- qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", QByteArray("1"));
+ qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", "1");
auto envRollback = qScopeGuard([]() { qunsetenv("QT_SSL_USE_TEMPORARY_KEYCHAIN"); });
#endif
@@ -1004,7 +1004,7 @@ void tst_Http2::contentEncoding()
// we have to use TLS sockets (== private key) and thus suppress a
// keychain UI asking for permission to use a private key.
// Our CI has this, but somebody testing locally - will have a problem.
- qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", QByteArray("1"));
+ qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", "1");
auto envRollback = qScopeGuard([]() { qunsetenv("QT_SSL_USE_TEMPORARY_KEYCHAIN"); });
#endif
diff --git a/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp b/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp
index 95998cd570..beb0a0805a 100644
--- a/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp
+++ b/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp
@@ -55,7 +55,7 @@ class tst_QAccessibilityLinux : public QObject
public:
tst_QAccessibilityLinux() : m_window(0), root(0), rootApplication(0), mainWindow(0)
{
- qputenv("QT_LINUX_ACCESSIBILITY_ALWAYS_ON", QByteArrayLiteral("1"));
+ qputenv("QT_LINUX_ACCESSIBILITY_ALWAYS_ON", "1");
dbus = new DBusConnection();
}
~tst_QAccessibilityLinux()
diff --git a/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp b/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp
index 15af4c899b..adf4cb7181 100644
--- a/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp
+++ b/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp
@@ -174,7 +174,7 @@ QString tst_QPrinterInfo::getOutputFromCommand(const QStringList &command)
{
// Forces the ouptut from the command to be in English
const QByteArray origSoftwareEnv = qgetenv("SOFTWARE");
- qputenv("SOFTWARE", QByteArray());
+ qputenv("SOFTWARE", nullptr);
QString output = getOutputFromCommandInternal(command);
qputenv("SOFTWARE", origSoftwareEnv);
return output;
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
index 3db9953471..127182fd90 100644
--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -1119,7 +1119,7 @@ void tst_QApplication::libraryPaths_qt_plugin_path_2()
<< QCoreApplication::applicationDirPath();
QVERIFY(isPathListIncluded(QCoreApplication::libraryPaths(), expected));
- qputenv("QT_PLUGIN_PATH", QByteArray());
+ qputenv("QT_PLUGIN_PATH", nullptr);
}
}
#endif