summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2020-09-16 20:48:38 -0700
committerThiago Macieira <thiago.macieira@intel.com>2020-10-08 03:54:16 +0000
commit9ef4fba108761bf30b9572fc53eaf98008bb4aae (patch)
tree580609a32ab502c41ce25557a06cfdf52865ef01
parent197e61711702ba1517e9e7e4219ca2801639197c (diff)
QUrl::fromLocalFile: accept invalid hostnames
QUrl hostnames must be compliant with STD3, but we must somehow accept file paths that begin with double slash but aren't valid hostnames. Because the file URI spec requires us to start with "file://" anyway, we can represent those with four slashes. Note that on Unix "//X/y" is a valid but local file path. If given to QUrl::fromLocalFile(), if the path at the root does parse as a hostname, we will still try to normalize (the above becomes "file://x/y"). [ChangeLog][QtCore][QUrl] Changed QUrl::fromLocalFile() to accept Windows UNC paths whose hostname component is not a valid Internet hostname. This makes QUrl able to accept extended-length paths (\\?\), device namespace (\\.\), WSL (\\wsl$), etc. Fixes: QTBUG-86277 Change-Id: I3eb349b832c14610895efffd1635759348214a3b Reviewed-by: David Faure <david.faure@kdab.com> (cherry picked from commit 97de53ee8cce3dc6347b08668f0de45e1000f01c)
-rw-r--r--src/corelib/io/qurl.cpp14
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp15
2 files changed, 26 insertions, 3 deletions
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 0c81af52d7..f7269798a3 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -3862,12 +3862,20 @@ QUrl QUrl::fromLocalFile(const QString &localFile)
hostSpec.truncate(hostSpec.size() - 4);
scheme = webDavScheme();
}
- url.setHost(hostSpec.toString());
- if (indexOfPath > 2)
+ // hosts can't be IPv6 addresses without [], so we can use QUrlPrivate::setHost
+ url.detach();
+ if (!url.d->setHost(hostSpec.toString(), 0, hostSpec.size(), StrictMode)) {
+ if (url.d->error->code != QUrlPrivate::InvalidRegNameError)
+ return url;
+
+ // Path hostname is not a valid URL host, so set it entirely in the path
+ // (by leaving deslashified unchanged)
+ } else if (indexOfPath > 2) {
deslashified = deslashified.right(deslashified.length() - indexOfPath);
- else
+ } else {
deslashified.clear();
+ }
}
url.setScheme(scheme);
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp
index d506ae5a66..d30ec1d57d 100644
--- a/tests/auto/corelib/io/qurl/tst_qurl.cpp
+++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp
@@ -1280,6 +1280,9 @@ void tst_QUrl::toLocalFile_data()
QTest::newRow("windows-unc-path") << QString::fromLatin1("file://somehost/somedir/somefile") << QString::fromLatin1("//somehost/somedir/somefile");
QTest::newRow("windows-unc-root") << QString::fromLatin1("file://somehost/") << QString::fromLatin1("//somehost/");
QTest::newRow("windows-unc-nopath") << QString::fromLatin1("file://somehost") << QString::fromLatin1("//somehost");
+ QTest::newRow("windows-extlen-path") << QString::fromLatin1("file:////%3F/somedir/somefile") << QString::fromLatin1("//?/somedir/somefile");
+ QTest::newRow("windows-wsl-path") << QString::fromLatin1("file:////wsl$/somedir/somefile") << QString::fromLatin1("//wsl$/somedir/somefile");
+ QTest::newRow("windows-device-path") << QString::fromLatin1("file:////./somedir/somefile") << QString::fromLatin1("//./somedir/somefile");
// and some that result in empty (i.e., not local)
QTest::newRow("noscheme-absolute") << QString::fromLatin1("/a.txt") << QString();
@@ -1332,6 +1335,18 @@ void tst_QUrl::fromLocalFile_data()
<< QString("file://somehost") + suffix
<< QString(suffix);
#endif
+ QTest::addRow("windows-extlen-%s", pathDescription)
+ << QString("//?") + suffix
+ << QString("file:////%3F") + suffix
+ << QString("//?") + suffix;
+ QTest::addRow("windows-wsl-%s", pathDescription)
+ << QString("//wsl$") + suffix
+ << QString("file:////wsl$") + suffix
+ << QString("//wsl$") + suffix;
+ QTest::addRow("windows-device--%s", pathDescription)
+ << QString("//.") + suffix
+ << QString("file:////.") + suffix
+ << QString("//.") + suffix;
}
QTest::newRow("windows-webdav")