qputenv: defend against non-NUL-terminated QByteArray values
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. Pick-to: 6.4 6.3 6.2 5.15 Fixes: QTBUG-105302 Change-Id: I3416535ab09d601e0e87b2767f2c024ba1217e64 Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
6a5cadb955
commit
15422d191f
@ -262,6 +262,14 @@ bool qEnvironmentVariableIsSet(const char *varName) noexcept
|
|||||||
*/
|
*/
|
||||||
bool qputenv(const char *varName, const QByteArray &value)
|
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)
|
#if defined(Q_CC_MSVC)
|
||||||
const auto locker = qt_scoped_lock(environmentMutex);
|
const auto locker = qt_scoped_lock(environmentMutex);
|
||||||
return _putenv_s(varName, value.constData()) == 0;
|
return _putenv_s(varName, value.constData()) == 0;
|
||||||
|
@ -60,7 +60,11 @@ void tst_QGetPutEnv::getSetCheck()
|
|||||||
QCOMPARE(sresult, QString());
|
QCOMPARE(sresult, QString());
|
||||||
#endif
|
#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(qEnvironmentVariableIsSet(varName));
|
||||||
QVERIFY(!qEnvironmentVariableIsEmpty(varName));
|
QVERIFY(!qEnvironmentVariableIsEmpty(varName));
|
||||||
|
Loading…
Reference in New Issue
Block a user