From 48d677365a1061aa973b38d7b640498830bda452 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 9 Dec 2017 22:18:02 -0800 Subject: [PATCH] QStandardPaths: fall back to a default if PATH isn't set Change 28666d167aa8e602c0bea25ebc4d51b55005db13 simplified QProcess::start{Process,Detached} by using findExecutable() instead of using execvp, but this introduced an unintended side effect when the PATH environment variable isn't set. It turns out that most libc have a default fallback in that situation, which we didn't apply. This commit applies the default directly to findExecutable(), which seems sensible. [ChangeLog][QtCore][QProcess] Fixed a regression that made QProcess be unable to find executables when the PATH environment variable on some Unix systems wasn't set. This behavior should not be relied upon since many systems do not have sensible fallback values for PATH. [ChangeLog][QtCore][QStandardPaths] findExecutable() will now apply the default value for the PATH environment variable (as returned by the POSIX confstr(3) function or found in ) if the variable isn't set in the environment. Task-number: QTBUG-65076 Change-Id: I9407dcf22de6407c83b5fffd14feda6c1f509210 Reviewed-by: Oswald Buddenhagen Reviewed-by: David Faure --- src/corelib/io/qstandardpaths.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index c3d45caf0e..b3a5bd797a 100644 --- a/src/corelib/io/qstandardpaths.cpp +++ b/src/corelib/io/qstandardpaths.cpp @@ -48,6 +48,14 @@ #include #endif +#if QT_HAS_INCLUDE() +#include +#endif + +#ifdef Q_OS_UNIX +#include +#endif + #ifndef QT_NO_STANDARDPATHS QT_BEGIN_NAMESPACE @@ -509,6 +517,27 @@ QString QStandardPaths::findExecutable(const QString &executableName, const QStr QStringList searchPaths = paths; if (paths.isEmpty()) { QByteArray pEnv = qgetenv("PATH"); + if (Q_UNLIKELY(pEnv.isNull())) { + // Get a default path. POSIX.1 does not actually require this, but + // most Unix libc fall back to confstr(_CS_PATH) if the PATH + // environment variable isn't set. Let's try to do the same. +#if defined(_PATH_DEFPATH) + // BSD API. + pEnv = _PATH_DEFPATH; +#elif defined(_CS_PATH) + // POSIX API. + size_t n = confstr(_CS_PATH, nullptr, 0); + if (n) { + pEnv.resize(n); + // size()+1 is ok because QByteArray always has an extra NUL-terminator + confstr(_CS_PATH, pEnv.data(), pEnv.size() + 1); + } +#else + // Windows SDK's execvpe() does not have a fallback, so we won't + // apply one either. +#endif + } + // Remove trailing slashes, which occur on Windows. const QStringList rawPaths = QString::fromLocal8Bit(pEnv.constData()).split(QDir::listSeparator(), QString::SkipEmptyParts); searchPaths.reserve(rawPaths.size());