From 0838ac541d38b33b23955c036bbcfd94ccc19066 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 31 Jul 2012 15:19:30 +0200 Subject: Make sure that the parsing mode reaches QUrlPrivate::setHost Ensure that the parsing mode is cascaded down from setAuthority and setUrl so that the hostname parsing does not attempt to decode percent-encoded hostnames when it shouldn't. Take the opportunity to also remove the "Boolean Trap" from QUrlPrivate::setHost. Change-Id: Ia64754c4a4900182700b7af1382aea8410abc7e9 Reviewed-by: Lars Knoll --- src/corelib/io/qurl.cpp | 18 +++++++++--------- src/corelib/io/qurl_p.h | 4 ++-- tests/auto/corelib/io/qurl/tst_qurl.cpp | 27 ++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index bc92e943fc..8cabc061fe 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -708,7 +708,7 @@ bool QUrlPrivate::setScheme(const QString &value, int len) return true; } -bool QUrlPrivate::setAuthority(const QString &auth, int from, int end) +bool QUrlPrivate::setAuthority(const QString &auth, int from, int end, QUrl::ParsingMode mode) { sectionHasError &= ~Authority; sectionIsPresent &= ~Authority; @@ -768,7 +768,7 @@ bool QUrlPrivate::setAuthority(const QString &auth, int from, int end) port = -1; } - return setHost(auth, from, qMin(end, colonIndex)) && !(sectionHasError & Port); + return setHost(auth, from, qMin(end, colonIndex), mode) && !(sectionHasError & Port); } void QUrlPrivate::setUserInfo(const QString &userInfo, int from, int end) @@ -955,7 +955,7 @@ static bool parseIp6(QString &host, const QChar *begin, const QChar *end) return true; } -bool QUrlPrivate::setHost(const QString &value, int from, int iend, bool maybePercentEncoded) +bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl::ParsingMode mode) { const QChar *begin = value.constData() + from; const QChar *end = value.constData() + iend; @@ -1020,7 +1020,7 @@ bool QUrlPrivate::setHost(const QString &value, int from, int iend, bool maybePe // check for percent-encoding first QString s; - if (maybePercentEncoded && qt_urlRecode(s, begin, end, QUrl::DecodeReserved, 0)) { + if (mode == QUrl::TolerantMode && qt_urlRecode(s, begin, end, QUrl::DecodeReserved, 0)) { // something was decoded // anything encoded left? if (s.contains(QChar(0x25))) { // '%' @@ -1030,7 +1030,7 @@ bool QUrlPrivate::setHost(const QString &value, int from, int iend, bool maybePe } // recurse - return setHost(s, 0, s.length(), false); + return setHost(s, 0, s.length(), QUrl::StrictMode); } s = qt_ACE_do(QString::fromRawData(begin, len), NormalizeAce); @@ -1111,7 +1111,7 @@ void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode) } } - setAuthority(url, hierStart + 2, authorityEnd); + setAuthority(url, hierStart + 2, authorityEnd, parsingMode); // even if we failed to set the authority properly, let's try to recover pathStart = authorityEnd; @@ -1649,7 +1649,7 @@ void QUrl::setAuthority(const QString &authority, ParsingMode mode) mode = TolerantMode; } - d->setAuthority(data, 0, data.length()); + d->setAuthority(data, 0, data.length(), mode); if (authority.isNull()) { // QUrlPrivate::setAuthority cleared almost everything // but it leaves the Host bit set @@ -1893,7 +1893,7 @@ void QUrl::setHost(const QString &host, ParsingMode mode) mode = TolerantMode; } - if (d->setHost(data, 0, data.length())) { + if (d->setHost(data, 0, data.length(), mode)) { if (host.isNull()) d->sectionIsPresent &= ~QUrlPrivate::Host; } else if (!data.startsWith(QLatin1Char('['))) { @@ -1902,7 +1902,7 @@ void QUrl::setHost(const QString &host, ParsingMode mode) ushort oldSupplement = d->errorSupplement; data.prepend(QLatin1Char('[')); data.append(QLatin1Char(']')); - if (!d->setHost(data, 0, data.length())) { + if (!d->setHost(data, 0, data.length(), mode)) { // failed again: choose if this was an IPv6 error or not if (!data.contains(QLatin1Char(':'))) { d->errorCode = oldCode; diff --git a/src/corelib/io/qurl_p.h b/src/corelib/io/qurl_p.h index 95ccd221a2..a1efb29ff8 100644 --- a/src/corelib/io/qurl_p.h +++ b/src/corelib/io/qurl_p.h @@ -123,11 +123,11 @@ public: // the "end" parameters are like STL iterators: they point to one past the last valid element bool setScheme(const QString &value, int len); - bool setAuthority(const QString &auth, int from, int end); + bool setAuthority(const QString &auth, int from, int end, QUrl::ParsingMode mode); void setUserInfo(const QString &userInfo, int from, int end); void setUserName(const QString &value, int from, int end); void setPassword(const QString &value, int from, int end); - bool setHost(const QString &value, int from, int end, bool maybePercentEncoded = true); + bool setHost(const QString &value, int from, int end, QUrl::ParsingMode mode); void setPath(const QString &value, int from, int end); void setQuery(const QString &value, int from, int end); void setFragment(const QString &value, int from, int end); diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index acde1f8871..6b7a8025ff 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -1842,6 +1842,7 @@ void tst_QUrl::strictParser_data() QTest::newRow("invalid-password") << "http://user:pass\x7F@ok-hostname" << "Invalid password"; QTest::newRow("invalid-regname") << "http://bad" << "Hostname contains invalid characters"; + QTest::newRow("invalid-regname-2") << "http://b%61d" << "Hostname contains invalid characters"; QTest::newRow("invalid-ipv6") << "http://[:::]" << "Invalid IPv6 address"; QTest::newRow("invalid-ipvfuture-1") << "http://[v7]" << "Invalid IPvFuture address"; QTest::newRow("invalid-ipvfuture-2") << "http://[v7.]" << "Invalid IPvFuture address"; @@ -2007,6 +2008,13 @@ void tst_QUrl::tolerantParser() QVERIFY(url.isValid()); QCOMPARE(QString(url.toEncoded()), QString("http://strange%3Cusername%3E@hostname/")); } + + { + QUrl url; + url.setUrl("http://en%63o%64%65%64.hostname/", QUrl::TolerantMode); + QVERIFY(url.isValid()); + QCOMPARE(url.toString(), QString("http://encoded.hostname/")); + } } void tst_QUrl::correctEncodedMistakes_data() @@ -3045,6 +3053,15 @@ void tst_QUrl::setComponents_data() QTest::newRow("invalid-host-1") << QUrl("http://example.com") << int(Host) << "-not-valid-" << Tolerant << false << PrettyDecoded << "" << ""; + QTest::newRow("invalid-host-2") << QUrl("http://example.com") + << int(Host) << "%31%30.%30.%30.%31" << Strict << false + << PrettyDecoded << "" << ""; + QTest::newRow("invalid-authority-1") << QUrl("http://example.com") + << int(Authority) << "-not-valid-" << Tolerant << false + << PrettyDecoded << "" << ""; + QTest::newRow("invalid-authority-2") << QUrl("http://example.com") + << int(Authority) << "%31%30.%30.%30.%31" << Strict << false + << PrettyDecoded << "" << ""; QTest::newRow("invalid-path-1") << QUrl("/relative") << int(Path) << "c:/" << Strict << false << PrettyDecoded << "" << ""; @@ -3063,10 +3080,13 @@ void tst_QUrl::setComponents_data() QTest::newRow("password-encode") << QUrl("http://example.com") << int(Password) << "h%61llo:world@" << Decoded << true << PrettyDecoded << "h%2561llo:world@" << "http://:h%2561llo:world%40@example.com"; - // '%' characters are not permitted in the hostname, this tests that it fails to set anything + // '%' characters are not permitted in the hostname, these test that it fails to set anything QTest::newRow("invalid-host-encode") << QUrl("http://example.com") << int(Host) << "ex%61mple.com" << Decoded << false << PrettyDecoded << "" << ""; + QTest::newRow("invalid-authority-encode") << QUrl("http://example.com") + << int(Authority) << "ex%61mple.com" << Decoded << false + << PrettyDecoded << "" << ""; QTest::newRow("path-encode") << QUrl("http://example.com/foo") << int(Path) << "bar%23" << Decoded << true << PrettyDecoded << "bar%2523" << "http://example.com/bar%2523"; @@ -3142,6 +3162,11 @@ void tst_QUrl::setComponents() QCOMPARE(copy.host(QUrl::ComponentFormattingOptions(encoding)), output); break; + case Authority: + copy.setAuthority(newValue, QUrl::ParsingMode(parsingMode)); + QCOMPARE(copy.authority(QUrl::ComponentFormattingOptions(encoding)), output); + break; + case Query: copy.setQuery(newValue, QUrl::ParsingMode(parsingMode)); QCOMPARE(copy.hasQuery(), !newValue.isNull()); -- cgit v1.2.3