From 9d0ff90760bed65451fb665fecf9f770e3b05967 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 1 Jul 2013 18:26:59 -0700 Subject: [PATCH] Make QUrl store the first bad IPv6 character in the error string Change-Id: I9a0a521ff5c3188ba6f862e2b91369cb61787359 Reviewed-by: David Faure (KDE) --- src/corelib/io/qurl.cpp | 33 ++++++++++++++++--------- tests/auto/corelib/io/qurl/tst_qurl.cpp | 2 ++ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index d7729b7cb9..3d7e18fdfa 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -374,6 +374,7 @@ public: InvalidRegNameError = Host << 8, InvalidIPv4AddressError, InvalidIPv6AddressError, + InvalidCharacterInIPv6Error, InvalidIPvFutureError, HostMissingEndBracket, @@ -1138,7 +1139,7 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar } // ONLY the IPv6 address is parsed here, WITHOUT the brackets -static bool parseIp6(QString &host, const QChar *begin, const QChar *end, QUrl::ParsingMode mode) +static const QChar *parseIp6(QString &host, const QChar *begin, const QChar *end, QUrl::ParsingMode mode) { QIPAddressUtils::IPv6Address address; const QChar *ret = QIPAddressUtils::parseIp6(address, begin, end); @@ -1149,21 +1150,24 @@ static bool parseIp6(QString &host, const QChar *begin, const QChar *end, QUrl:: // IPv6 failed parsing, check if it was a percent-encoded character in // the middle and try again QString decoded; - if (mode != QUrl::TolerantMode || !qt_urlRecode(decoded, begin, end, 0, decodeColon)) { - // no transformation, nothing to re-parse - return false; + if (mode == QUrl::TolerantMode && qt_urlRecode(decoded, begin, end, 0, decodeColon)) { + // recurse + // if the parsing fails again, the qt_urlRecode above will return 0 + ret = parseIp6(host, decoded.constBegin(), decoded.constEnd(), mode); + + // we can't return ret, otherwise it would be dangling + return ret ? end : 0; } - // recurse - // if the parsing fails again, the qt_urlRecode above will return 0 - return parseIp6(host, decoded.constBegin(), decoded.constEnd(), mode); + // no transformation, nothing to re-parse + return ret; } host.reserve(host.size() + (end - begin)); host += QLatin1Char('['); QIPAddressUtils::toString(host, address); host += QLatin1Char(']'); - return true; + return 0; } inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl::ParsingMode mode) @@ -1191,13 +1195,18 @@ inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl: if (c) setError(InvalidIPvFutureError, value, c - value.constData()); return !c; + } else if (begin[1].unicode() == 'v') { + setError(InvalidIPvFutureError, value, from); } - if (parseIp6(host, begin + 1, end - 1, mode)) + const QChar *c = parseIp6(host, begin + 1, end - 1, mode); + if (!c) return true; - setError(begin[1].unicode() == 'v' ? InvalidIPvFutureError : InvalidIPv6AddressError, - value, from); + if (c == end - 1) + setError(InvalidIPv6AddressError, value, from); + else + setError(InvalidCharacterInIPv6Error, value, c - value.constData()); return false; } @@ -3659,6 +3668,8 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err return QString(); // doesn't happen yet case QUrlPrivate::InvalidIPv6AddressError: return QStringLiteral("Invalid IPv6 address"); + case QUrlPrivate::InvalidCharacterInIPv6Error: + return QStringLiteral("Invalid IPv6 address (character '%1' not permitted)").arg(c); case QUrlPrivate::InvalidIPvFutureError: return QStringLiteral("Invalid IPvFuture address (character '%1' not permitted)").arg(c); case QUrlPrivate::HostMissingEndBracket: diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index 105485ca5f..5230dbe109 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -2012,6 +2012,8 @@ void tst_QUrl::strictParser_data() QTest::newRow("invalid-regname") << "http://bad" << "Invalid hostname (contains invalid characters)"; QTest::newRow("invalid-regname-2") << "http://b%61d" << "Invalid hostname (contains invalid characters)"; QTest::newRow("invalid-ipv6") << "http://[:::]" << "Invalid IPv6 address"; + QTest::newRow("invalid-ipv6-char1") << "http://[::g]" << "Invalid IPv6 address (character 'g' not permitted)"; + QTest::newRow("invalid-ipv6-char2") << "http://[z::]" << "Invalid IPv6 address (character 'z' not permitted)"; QTest::newRow("invalid-ipvfuture-1") << "http://[v7]" << "Invalid IPvFuture address"; QTest::newRow("invalid-ipvfuture-2") << "http://[v7.]" << "Invalid IPvFuture address"; QTest::newRow("invalid-ipvfuture-3") << "http://[v789]" << "Invalid IPvFuture address";