From b52b509ae48125ce9ba3cb50560e2e9ff81b485e Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 27 Feb 2017 14:03:15 +0100 Subject: QLockFile: Don't deadlock if the lock file has a mtime in the future Stale Lock files in the future can happen in some situations. For exemple two computers with different clocks access the same file system. It could be that one of the timestamp is totaly off (several years into the future). [ChangeLog][QtCore][QLockFile] Fixed a deadlock occurring if a corrupted lock file's modification time is in the future. Change-Id: I8dac98a0e898c76bcef67f8c195e126c996b6add Reviewed-by: David Faure --- src/corelib/io/qlockfile.cpp | 3 +++ src/corelib/io/qlockfile_unix.cpp | 2 +- src/corelib/io/qlockfile_win.cpp | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qlockfile.cpp b/src/corelib/io/qlockfile.cpp index cb1ff93ad3..48317d07e0 100644 --- a/src/corelib/io/qlockfile.cpp +++ b/src/corelib/io/qlockfile.cpp @@ -44,6 +44,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -226,6 +227,8 @@ bool QLockFile::tryLock(int timeout) return false; case LockFailedError: if (!d->isLocked && d->isApparentlyStale()) { + if (Q_UNLIKELY(QFileInfo(d->fileName).lastModified() > QDateTime::currentDateTime())) + qInfo("QLockFile: Lock file '%ls' has a modification time in the future", qUtf16Printable(d->fileName)); // Stale lock from another thread/process // Ensure two processes don't remove it at the same time QLockFile rmlock(d->fileName + QLatin1String(".rmlock")); diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 3a80014c00..5a02741727 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -247,7 +247,7 @@ bool QLockFilePrivate::isApparentlyStale() const } } const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); - return staleLockTime > 0 && age > staleLockTime; + return staleLockTime > 0 && qAbs(age) > staleLockTime; } QString QLockFilePrivate::processNameByPid(qint64 pid) diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp index baaff8da17..4b43181686 100644 --- a/src/corelib/io/qlockfile_win.cpp +++ b/src/corelib/io/qlockfile_win.cpp @@ -160,7 +160,7 @@ bool QLockFilePrivate::isApparentlyStale() const Q_UNUSED(appname); #endif // Q_OS_WINRT const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); - return staleLockTime > 0 && age > staleLockTime; + return staleLockTime > 0 && qAbs(age) > staleLockTime; } QString QLockFilePrivate::processNameByPid(qint64 pid) -- cgit v1.2.3 From c0da37a806dc0457636d787331e9f50778ee8b3e Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Thu, 9 Mar 2017 10:47:04 -0800 Subject: Fix QStandardPaths values on Apple Platforms containing URL encoding This corrects an issue where the file system paths returned for some QStandardPaths values on Apple Platforms would be URL encoded, for example having %20 instead of an actual space character. Task-number: QTBUG-59389 Change-Id: I771a44eb20b756842c324ac6fc9bdc475ce84826 Reviewed-by: David Faure Reviewed-by: Timur Pocheptsov Reviewed-by: Gabriel de Dietrich --- src/corelib/io/qstandardpaths_mac.mm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qstandardpaths_mac.mm b/src/corelib/io/qstandardpaths_mac.mm index a293d4862f..e25339a7d1 100644 --- a/src/corelib/io/qstandardpaths_mac.mm +++ b/src/corelib/io/qstandardpaths_mac.mm @@ -204,13 +204,14 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) CFBundleRef mainBundle = CFBundleGetMainBundle(); if (mainBundle) { CFURLRef bundleUrl = CFBundleCopyBundleURL(mainBundle); - CFStringRef cfBundlePath = CFURLCopyPath(bundleUrl); + CFStringRef cfBundlePath = CFURLCopyFileSystemPath(bundleUrl, kCFURLPOSIXPathStyle); QString bundlePath = QString::fromCFString(cfBundlePath); CFRelease(cfBundlePath); CFRelease(bundleUrl); CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL(mainBundle); - CFStringRef cfResourcesPath = CFURLCopyPath(resourcesUrl); + CFStringRef cfResourcesPath = CFURLCopyFileSystemPath(resourcesUrl, + kCFURLPOSIXPathStyle); QString resourcesPath = QString::fromCFString(cfResourcesPath); CFRelease(cfResourcesPath); CFRelease(resourcesUrl); -- cgit v1.2.3 From 4ee74257940e2ed21b653b986ad02a746e8438a6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 16 Mar 2017 21:36:17 -0700 Subject: Work around Linux libc overflow in mmap64 The mmap64 functions in all Linux libc fail to properly check that the value fits in the system call parameter. I guess the developers just said "16 PB are enough for everyone"... Change-Id: Ic39b2c4fd9c84522a8fafffd14ac91567ce09c09 Reviewed-by: Sami Nurmenniemi Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qfsfileengine_unix.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index bf2f47d399..f8e31ed92b 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -688,6 +688,19 @@ QDateTime QFSFileEngine::fileTime(FileTime time) const uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags) { +#if (defined(Q_OS_LINUX) || defined(Q_OS_ANDROID)) && Q_PROCESSOR_WORDSIZE == 4 + // The Linux mmap2 system call on 32-bit takes a page-shifted 32-bit + // integer so the maximum offset is 1 << (32+12) (the shift is always 12, + // regardless of the actual page size). Unfortunately, the mmap64() + // function is known to be broken in all Linux libcs (glibc, uclibc, musl + // and Bionic): all of them do the right shift, but don't confirm that the + // result fits into the 32-bit parameter to the kernel. + + static qint64 MaxFileOffset = (Q_INT64_C(1) << (32+12)) - 1; +#else + static qint64 MaxFileOffset = std::numeric_limits::max(); +#endif + Q_Q(QFSFileEngine); Q_UNUSED(flags); if (openMode == QIODevice::NotOpen) { @@ -695,7 +708,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla return 0; } - if (offset < 0 || offset != qint64(QT_OFF_T(offset)) + if (offset < 0 || offset > MaxFileOffset || size < 0 || quint64(size) > quint64(size_t(-1))) { q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL))); return 0; -- cgit v1.2.3 From 035e0eafa607217f8110a492a9be7d0718e34907 Mon Sep 17 00:00:00 2001 From: David Faure Date: Wed, 15 Mar 2017 12:03:18 +0100 Subject: QUrl::fromUserInput: fix handling of files with a ':' in the name QUrl::isRelative(str) would be false for such files, so first check for file existence before doing any URL parsing. Change-Id: I51b6229251ad94877ac408b2f8018456d3e10a36 Reviewed-by: Shawn Rutledge Reviewed-by: Thiago Macieira --- src/corelib/io/qurl.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 520ad2e5d3..3df7070557 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -4170,12 +4170,15 @@ QUrl QUrl::fromUserInput(const QString &userInput, const QString &workingDirecto return url; } + const QFileInfo fileInfo(QDir(workingDirectory), userInput); + if (fileInfo.exists()) { + return QUrl::fromLocalFile(fileInfo.absoluteFilePath()); + } + QUrl url = QUrl(userInput, QUrl::TolerantMode); // Check both QUrl::isRelative (to detect full URLs) and QDir::isAbsolutePath (since on Windows drive letters can be interpreted as schemes) - if (url.isRelative() && !QDir::isAbsolutePath(userInput)) { - QFileInfo fileInfo(QDir(workingDirectory), userInput); - if ((options & AssumeLocalFile) || fileInfo.exists()) - return QUrl::fromLocalFile(fileInfo.absoluteFilePath()); + if ((options & AssumeLocalFile) && url.isRelative() && !QDir::isAbsolutePath(userInput)) { + return QUrl::fromLocalFile(fileInfo.absoluteFilePath()); } return fromUserInput(trimmedString); -- cgit v1.2.3 From 9021a748afc9a380feb80dc4d1a824c4d77f2aa1 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 17 Mar 2017 14:03:08 -0700 Subject: QStorageInfo: Fix warning about unused variable Happens on non-Linux, non-macOS Unix systems (got it on FreeBSD). Change-Id: Ie67d35dff21147e99ad9fffd14acc7308b5ff17e Reviewed-by: Jake Petroules Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qstorageinfo_unix.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index fcc7b8ca50..b9c9883609 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -503,6 +503,8 @@ static QByteArray extractSubvolume(const QStorageIterator &it) // if we didn't find the subvolume name, return the subvolume ID return id; } +#else + Q_UNUSED(it); #endif return QByteArray(); } -- cgit v1.2.3 From e19fda916aa92f8890199dc4b9d56884c55d0cd8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 23 Mar 2017 15:18:00 -0700 Subject: Fix some warnings found by QNX's compiler -Werror is now disabled for that compiler, but it doesn't hurt to fix. io/qstandardpaths_unix.cpp:149:32: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare] qtestcase.cpp:2330:31: error: narrowing conversion of '(ms / 1000)' from 'int' to '_Timet {aka unsigned int}' inside { } [-Werror=narrowing] Change-Id: Id92f4a61915b49ddaee6fffd14aea2c1e686e8f2 Reviewed-by: Samuli Piippo --- src/corelib/io/qstandardpaths_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp index 7974dc8cca..f0ff46fe7f 100644 --- a/src/corelib/io/qstandardpaths_unix.cpp +++ b/src/corelib/io/qstandardpaths_unix.cpp @@ -117,7 +117,7 @@ QString QStandardPaths::writableLocation(StandardLocation type) } case RuntimeLocation: { - const uid_t myUid = geteuid(); + const uint myUid = uint(geteuid()); // http://standards.freedesktop.org/basedir-spec/latest/ QFileInfo fileInfo; QString xdgRuntimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR")); -- cgit v1.2.3 From d8e2db017392cff7c57cab0d271e5677109f3bd7 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 22 Mar 2017 14:27:25 +0100 Subject: QDir: replace QLVA with QVLA ... as used in qstring.cpp, too. QChar is only marked as movable, not primitive, as it should have been and ushort is, and there's some hope that the template instantiations can be shared across TUs. Saves a rather disappointing 148B in text size on optimized GCC 7 Linux AMD64 builds. Change-Id: Ic9558a4d83611a6461cd5540c9090cbd4c4f2f4e Reviewed-by: Thiago Macieira --- src/corelib/io/qdir.cpp | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index bfb91c131f..6d144cb65d 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -2105,11 +2105,11 @@ Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool all return name; int i = len - 1; - QVarLengthArray outVector(len); + QVarLengthArray outVector(len); int used = len; - QChar *out = outVector.data(); - const QChar *p = name.unicode(); - const QChar *prefix = p; + ushort *out = outVector.data(); + const ushort *p = name.utf16(); + const ushort *prefix = p; int up = 0; const int prefixLength = rootLength(name, allowUncPaths); @@ -2117,39 +2117,39 @@ Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool all i -= prefixLength; // replicate trailing slash (i > 0 checks for emptiness of input string p) - if (i > 0 && p[i].unicode() == '/') { - out[--used].unicode() = '/'; + if (i > 0 && p[i] == '/') { + out[--used] = '/'; --i; } while (i >= 0) { // remove trailing slashes - if (p[i].unicode() == '/') { + if (p[i] == '/') { --i; continue; } // remove current directory - if (p[i].unicode() == '.' && (i == 0 || p[i-1].unicode() == '/')) { + if (p[i] == '.' && (i == 0 || p[i-1] == '/')) { --i; continue; } // detect up dir - if (i >= 1 && p[i].unicode() == '.' && p[i-1].unicode() == '.' - && (i == 1 || (i >= 2 && p[i-2].unicode() == '/'))) { + if (i >= 1 && p[i] == '.' && p[i-1] == '.' + && (i == 1 || (i >= 2 && p[i-2] == '/'))) { ++up; i -= 2; continue; } // prepend a slash before copying when not empty - if (!up && used != len && out[used].unicode() != '/') - out[--used] = QLatin1Char('/'); + if (!up && used != len && out[used] != '/') + out[--used] = '/'; // skip or copy while (i >= 0) { - if (p[i].unicode() == '/') { // do not copy slashes + if (p[i] == '/') { // do not copy slashes --i; break; } @@ -2171,17 +2171,17 @@ Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool all // add remaining '..' while (up) { - if (used != len && out[used].unicode() != '/') // is not empty and there isn't already a '/' - out[--used] = QLatin1Char('/'); - out[--used] = QLatin1Char('.'); - out[--used] = QLatin1Char('.'); + if (used != len && out[used] != '/') // is not empty and there isn't already a '/' + out[--used] = '/'; + out[--used] = '.'; + out[--used] = '.'; --up; } bool isEmpty = used == len; if (prefixLength) { - if (!isEmpty && out[used].unicode() == '/') { + if (!isEmpty && out[used] == '/') { // Eventhough there is a prefix the out string is a slash. This happens, if the input // string only consists of a prefix followed by one or more slashes. Just skip the slash. ++used; @@ -2192,18 +2192,19 @@ Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool all if (isEmpty) { // After resolving the input path, the resulting string is empty (e.g. "foo/.."). Return // a dot in that case. - out[--used] = QLatin1Char('.'); - } else if (out[used].unicode() == '/') { + out[--used] = '.'; + } else if (out[used] == '/') { // After parsing the input string, out only contains a slash. That happens whenever all // parts are resolved and there is a trailing slash ("./" or "foo/../" for example). // Prepend a dot to have the correct return value. - out[--used] = QLatin1Char('.'); + out[--used] = '.'; } } // If path was not modified return the original value - QString ret = (used == 0 ? name : QString(out + used, len - used)); - return ret; + if (used == 0) + return name; + return QString::fromUtf16(out + used, len - used); } static QString qt_cleanPath(const QString &path, bool *ok) -- cgit v1.2.3