summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2022-08-06 08:54:17 +0200
committerMarc Mutz <marc.mutz@qt.io>2022-08-08 09:39:41 +0000
commit3e8530d7011fb5d569d4c0becaf59461e310f1ea (patch)
treeb9b83278d038247415ba0c5754d5c70dd64cb6df
parent1af74fffd0e11f843afe61240b6b4dabecc1821b (diff)
qputenv: defend against non-NUL-terminated QByteArray values6.4
The old code assumed that a QByteArray's data() is always NUL-terminated. Due to the conflation of owners and non-owners in QByteArray (but also in case we ever get efficient substringing), this is not always the case, e.g. QByteArray::fromRawData() does not ensure NUL-termination. From QString::utf16(), we learn that the condition to check for is QArrayData::isMutable(). After working around the fact that QByteArray::data_ptr() doesn't exist for const QBAs and that empty QBAs always refer to QByteArray::empty_, which is !isMutable(), we can detect this situation and re-allocate without introducing new API. This is the fix for Qt ≤ 6.4. For Qt 6.5, we'll port the function to QByteArrayView. Manual conflict resolutions: - tracked changes into qglobal.cpp (was: qenvionmentvariables.cpp) Fixes: QTBUG-105302 Change-Id: I3416535ab09d601e0e87b2767f2c024ba1217e64 Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> (cherry picked from commit 15422d191fb03eb9cafe68b24484d59c1270244c)
-rw-r--r--src/corelib/global/qglobal.cpp8
-rw-r--r--tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp6
2 files changed, 13 insertions, 1 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index d2805f52e1..3d880fdb46 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -3619,6 +3619,14 @@ bool qEnvironmentVariableIsSet(const char *varName) noexcept
*/
bool qputenv(const char *varName, const QByteArray &value)
{
+ // 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);
+ }
+
#if defined(Q_CC_MSVC)
const auto locker = qt_scoped_lock(environmentMutex);
return _putenv_s(varName, value.constData()) == 0;
diff --git a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
index 77a7fa4194..f914ee5f23 100644
--- a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
+++ b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
@@ -60,7 +60,11 @@ void tst_QGetPutEnv::getSetCheck()
QCOMPARE(sresult, QString());
#endif
- QVERIFY(qputenv(varName, QByteArray("supervalue")));
+ constexpr char varValueFullString[] = "supervalue123";
+ const auto varValueQBA = QByteArray::fromRawData(varValueFullString, sizeof varValueFullString - 4);
+ QCOMPARE_EQ(varValueQBA, "supervalue");
+
+ QVERIFY(qputenv(varName, varValueQBA));
QVERIFY(qEnvironmentVariableIsSet(varName));
QVERIFY(!qEnvironmentVariableIsEmpty(varName));