diff options
author | Ievgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io> | 2021-10-14 15:14:00 +0200 |
---|---|---|
committer | Ievgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io> | 2021-11-07 01:53:44 +0100 |
commit | 5fc9c02a695edca23c0f8b2ec4c258e2c4212ea8 (patch) | |
tree | 67bed0f375fc5b05eeb34251574c21500ad8ff29 /src/corelib/io/qprocess_win.cpp | |
parent | 7f8fd38931a86288bcf8dac7f4a249db259fd33e (diff) |
QProcess: Distinguish between null and empty QProcessEnvironment
The documentation for QProcessEnvironment's default constructor
says:
This constructor creates an empty environment. If set on a
QProcess, this will cause the current environment variables
to be removed.
This is not the case however, because setting such an environment
for a process is equivalent to not setting an environment at all
and the child process is executed with parent's environment.
It is still possible starting from Qt 6.2.0 to create an empty
environment by adding a variable to a null environment and removing
it, but that's cumbersome, and the comparison operator says that
it is equal to the null environment but it is obviously behaving in
a different way.
This change adds an additional constructor to QProcessEnvironment
that can be used to construct a null environment, and changes the
default constructor to produce an empty environment. The comparison
operator is changed to correctly distinguish between such objects.
This is a behavior change, but the current behavior is broken
and this is unlikely to affect working code.
[ChangeLog][QtCore][QProcessEnvironment] An additional constructor
was added to explicitly create an object that when set on QProcess
would cause it to inherit the environment from parent (this was
formerly the behavior of a default-constructed QProcessEnvironment,
which will now (as documented) actually give a process an environment
with no variables set). A new method inheritsFromParent() was added
to test for such objects.
Fixes: QTBUG-58053
Change-Id: I15e20c6a5f01ebe2c736d5578c75dba1ee319320
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/io/qprocess_win.cpp')
-rw-r--r-- | src/corelib/io/qprocess_win.cpp | 95 |
1 files changed, 47 insertions, 48 deletions
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index c1084d72a1..d316af7c38 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -438,60 +438,59 @@ static QString qt_create_commandline(const QString &program, const QStringList & static QByteArray qt_create_environment(const QProcessEnvironmentPrivate::Map &environment) { QByteArray envlist; - if (!environment.isEmpty()) { - QProcessEnvironmentPrivate::Map copy = environment; - - // add PATH if necessary (for DLL loading) - QProcessEnvironmentPrivate::Key pathKey(QLatin1String("PATH")); - if (!copy.contains(pathKey)) { - QByteArray path = qgetenv("PATH"); - if (!path.isEmpty()) - copy.insert(pathKey, QString::fromLocal8Bit(path)); - } + QProcessEnvironmentPrivate::Map copy = environment; - // add systemroot if needed - QProcessEnvironmentPrivate::Key rootKey(QLatin1String("SystemRoot")); - if (!copy.contains(rootKey)) { - QByteArray systemRoot = qgetenv("SystemRoot"); - if (!systemRoot.isEmpty()) - copy.insert(rootKey, QString::fromLocal8Bit(systemRoot)); - } + // add PATH if necessary (for DLL loading) + QProcessEnvironmentPrivate::Key pathKey(QLatin1String("PATH")); + if (!copy.contains(pathKey)) { + QByteArray path = qgetenv("PATH"); + if (!path.isEmpty()) + copy.insert(pathKey, QString::fromLocal8Bit(path)); + } - qsizetype pos = 0; - auto it = copy.constBegin(); - const auto end = copy.constEnd(); + // add systemroot if needed + QProcessEnvironmentPrivate::Key rootKey(QLatin1String("SystemRoot")); + if (!copy.contains(rootKey)) { + QByteArray systemRoot = qgetenv("SystemRoot"); + if (!systemRoot.isEmpty()) + copy.insert(rootKey, QString::fromLocal8Bit(systemRoot)); + } - static const wchar_t equal = L'='; - static const wchar_t nul = L'\0'; + qsizetype pos = 0; + auto it = copy.constBegin(); + const auto end = copy.constEnd(); - for ( ; it != end; ++it) { - qsizetype tmpSize = sizeof(wchar_t) * (it.key().length() + it.value().length() + 2); - // ignore empty strings - if (tmpSize == sizeof(wchar_t) * 2) - continue; - envlist.resize(envlist.size() + tmpSize); + static const wchar_t equal = L'='; + static const wchar_t nul = L'\0'; - tmpSize = it.key().length() * sizeof(wchar_t); - memcpy(envlist.data()+pos, it.key().utf16(), tmpSize); - pos += tmpSize; + for (; it != end; ++it) { + qsizetype tmpSize = sizeof(wchar_t) * (it.key().length() + it.value().length() + 2); + // ignore empty strings + if (tmpSize == sizeof(wchar_t) * 2) + continue; + envlist.resize(envlist.size() + tmpSize); - memcpy(envlist.data()+pos, &equal, sizeof(wchar_t)); - pos += sizeof(wchar_t); + tmpSize = it.key().length() * sizeof(wchar_t); + memcpy(envlist.data() + pos, it.key().utf16(), tmpSize); + pos += tmpSize; - tmpSize = it.value().length() * sizeof(wchar_t); - memcpy(envlist.data()+pos, it.value().utf16(), tmpSize); - pos += tmpSize; + memcpy(envlist.data() + pos, &equal, sizeof(wchar_t)); + pos += sizeof(wchar_t); - memcpy(envlist.data()+pos, &nul, sizeof(wchar_t)); - pos += sizeof(wchar_t); - } - // add the 2 terminating 0 (actually 4, just to be on the safe side) - envlist.resize( envlist.size()+4 ); - envlist[pos++] = 0; - envlist[pos++] = 0; - envlist[pos++] = 0; - envlist[pos++] = 0; + tmpSize = it.value().length() * sizeof(wchar_t); + memcpy(envlist.data() + pos, it.value().utf16(), tmpSize); + pos += tmpSize; + + memcpy(envlist.data() + pos, &nul, sizeof(wchar_t)); + pos += sizeof(wchar_t); } + // add the 2 terminating 0 (actually 4, just to be on the safe side) + envlist.resize(envlist.size() + 4); + envlist[pos++] = 0; + envlist[pos++] = 0; + envlist[pos++] = 0; + envlist[pos++] = 0; + return envlist; } @@ -564,7 +563,7 @@ void QProcessPrivate::startProcess() const QString args = qt_create_commandline(program, arguments, nativeArguments); QByteArray envlist; - if (environment.d.constData()) + if (!environment.inheritsFromParent()) envlist = qt_create_environment(environment.d.constData()->vars); #if defined QPROCESS_DEBUG @@ -586,7 +585,7 @@ void QProcessPrivate::startProcess() QProcess::CreateProcessArguments cpargs = { nullptr, reinterpret_cast<wchar_t *>(const_cast<ushort *>(args.utf16())), nullptr, nullptr, true, dwCreationFlags, - environment.isEmpty() ? nullptr : envlist.data(), + environment.inheritsFromParent() ? nullptr : envlist.data(), nativeWorkingDirectory.isEmpty() ? nullptr : reinterpret_cast<const wchar_t *>(nativeWorkingDirectory.utf16()), &startupInfo, pid @@ -926,7 +925,7 @@ bool QProcessPrivate::startDetached(qint64 *pid) void *envPtr = nullptr; QByteArray envlist; - if (environment.d.constData()) { + if (!environment.inheritsFromParent()) { envlist = qt_create_environment(environment.d.constData()->vars); envPtr = envlist.data(); } |