summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qdir.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2025-02-02 10:45:49 -0800
committerThiago Macieira <thiago.macieira@intel.com>2025-02-04 11:37:31 -0800
commit340c9d88ab353e201f117d64609fa5f7d2fa2b21 (patch)
tree06f10c09c03cbbec052b56b0dcf346771d68a077 /src/corelib/io/qdir.cpp
parent7d05f5ed7d3472028e28a09eeda175bb1b1eeb00 (diff)
QUrl: avoid going up from the drive path on Windows file URLs
On Windows, using a URL of "file:///c:/" as a base to be resolved with "../" should not result in the Windows drive being removed. [ChangeLog][QtCore][QUrl] Fixed a bug (regression from 6.7) where resolving a base URL of an absolute file path containing a Windows drive could result in said drive being removed (e.g., resolving "file:///c:/" with "../" would result in "file:///"). Fixes: QTBUG-133402 Pick-to: 6.9 6.8 Change-Id: I58286b9c5e5d02363f0efffdb06f983b560340df Reviewed-by: David Faure <david.faure@kdab.com>
Diffstat (limited to 'src/corelib/io/qdir.cpp')
-rw-r--r--src/corelib/io/qdir.cpp41
1 files changed, 29 insertions, 12 deletions
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 58fccc2e7c2..227aa936318 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -52,23 +52,40 @@ static QString driveSpec(const QString &path)
#endif
// Return the length of the root part of an absolute path, for use by cleanPath(), cd().
-static qsizetype rootLength(QStringView name)
+static qsizetype rootLength(QStringView name, QDirPrivate::PathNormalizations flags)
{
+ constexpr bool UseWindowsRules = false // So we don't #include <QOperatingSystemVersion>
#if defined(Q_OS_WIN)
+ || true
+#endif
+ ;
const qsizetype len = name.size();
- // Handle possible UNC paths which start with double slash
- if (name.startsWith("//"_L1)) {
- // Server name '//server/path' is part of the prefix.
- const qsizetype nextSlash = name.indexOf(u'/', 2);
- return nextSlash >= 0 ? nextSlash + 1 : len;
- }
- if (len >= 2 && name.at(1) == u':') {
+ char16_t firstChar = len > 0 ? name.at(0).unicode() : u'\0';
+ char16_t secondChar = len > 1 ? name.at(1).unicode() : u'\0';
+ if constexpr (UseWindowsRules) {
+ // Handle possible UNC paths which start with double slash
+ bool urlMode = flags.testAnyFlags(QDirPrivate::UrlNormalizationMode);
+ if (firstChar == u'/' && secondChar == u'/' && !urlMode) {
+ // Server name '//server/path' is part of the prefix.
+ const qsizetype nextSlash = name.indexOf(u'/', 2);
+ return nextSlash >= 0 ? nextSlash + 1 : len;
+ }
+
// Handle a possible drive letter
- return len > 2 && name.at(2) == u'/' ? 3 : 2;
+ qsizetype driveLength = 2;
+ if (firstChar == u'/' && urlMode && len > 2 && name.at(2) == u':') {
+ // Drive-in-URL-Path mode, e.g. "/c:" or "/c:/autoexec.bat"
+ ++driveLength;
+ secondChar = u':';
+ }
+ if (secondChar == u':') {
+ if (len > driveLength && name.at(driveLength) == u'/')
+ return driveLength + 1; // absolute drive path, e.g. "c:/config.sys"
+ return driveLength; // relative drive path, e.g. "c:" or "d:swapfile.sys"
+ }
}
-#endif
- return name.startsWith(u'/') ? 1 : 0;
+ return firstChar == u'/' ? 1 : 0;
}
//************* QDirPrivate
@@ -2217,7 +2234,7 @@ bool QDir::match(const QString &filter, const QString &fileName)
bool qt_normalizePathSegments(QString *path, QDirPrivate::PathNormalizations flags)
{
const bool isRemote = flags.testAnyFlag(QDirPrivate::RemotePath);
- const qsizetype prefixLength = rootLength(*path);
+ const qsizetype prefixLength = rootLength(*path, flags);
// RFC 3986 says: "The input buffer is initialized with the now-appended
// path components and the output buffer is initialized to the empty