summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2013-07-01 18:24:40 -0700
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-07-20 05:08:08 +0200
commit9063119268821a5ea5c1fec0156efa72b84752c6 (patch)
treed2e4a9635f80557b043882957b5cec5dfcaecca0 /src
parent4b3acf5aff76344aab4584b5c54b74d189b19246 (diff)
Make QIPAddress::parseIp6 return the first bad character
In case of undetermined error, returns end. Change-Id: Ic5d16bab5fc56ad24f19da25f73f9b844ce11d3f Reviewed-by: David Faure (KDE) <faure@kde.org>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/io/qipaddress.cpp60
-rw-r--r--src/corelib/io/qipaddress_p.h2
-rw-r--r--src/corelib/io/qurl.cpp3
-rw-r--r--src/network/kernel/qhostaddress.cpp2
4 files changed, 40 insertions, 27 deletions
diff --git a/src/corelib/io/qipaddress.cpp b/src/corelib/io/qipaddress.cpp
index bd36d36ac1..334c239c91 100644
--- a/src/corelib/io/qipaddress.cpp
+++ b/src/corelib/io/qipaddress.cpp
@@ -53,7 +53,7 @@ static QString number(quint8 val, int base = 10)
}
typedef QVarLengthArray<char, 64> Buffer;
-static bool checkedToAscii(Buffer &buffer, const QChar *begin, const QChar *end)
+static const QChar *checkedToAscii(Buffer &buffer, const QChar *begin, const QChar *end)
{
const ushort *const ubegin = reinterpret_cast<const ushort *>(begin);
const ushort *const uend = reinterpret_cast<const ushort *>(end);
@@ -64,11 +64,11 @@ static bool checkedToAscii(Buffer &buffer, const QChar *begin, const QChar *end)
while (src != uend) {
if (*src >= 0x7f)
- return false;
+ return reinterpret_cast<const QChar *>(src);
*dst++ = *src++;
}
*dst = '\0';
- return true;
+ return 0;
}
static bool parseIp4Internal(IPv4Address &address, const char *ptr, bool acceptLeadingZero);
@@ -76,7 +76,7 @@ bool parseIp4(IPv4Address &address, const QChar *begin, const QChar *end)
{
Q_ASSERT(begin != end);
Buffer buffer;
- if (!checkedToAscii(buffer, begin, end))
+ if (checkedToAscii(buffer, begin, end))
return false;
const char *ptr = buffer.data();
@@ -137,12 +137,23 @@ void toString(QString &appendTo, IPv4Address address)
% number(address);
}
-bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
+/*!
+ \internal
+ \since 5.0
+
+ Parses one IPv6 address from \a begin to \a end and stores the
+ representation in \a address. Returns null if everything was parsed
+ correctly, or the pointer to the first bad character where parsing failed.
+ If the parsing failed for a reason not related to a particular character,
+ returns \a end.
+*/
+const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
{
Q_ASSERT(begin != end);
Buffer buffer;
- if (!checkedToAscii(buffer, begin, end))
- return false;
+ const QChar *ret = checkedToAscii(buffer, begin, end);
+ if (ret)
+ return ret;
const char *ptr = buffer.data();
@@ -158,11 +169,11 @@ bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
}
// IPv4-in-IPv6 addresses are stricter in what they accept
if (dotCount != 0 && dotCount != 3)
- return false;
+ return end;
memset(address, 0, sizeof address);
if (colonCount == 2 && end - begin == 2) // "::"
- return true;
+ return 0;
// if there's a double colon ("::"), this is how many zeroes it means
int zeroWordsToFill;
@@ -174,7 +185,7 @@ bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
(ptr[end - begin - 2] == ':' && ptr[end - begin - 1] == ':')) {
zeroWordsToFill = 9 - colonCount;
} else if (colonCount < 2 || colonCount > 7) {
- return false;
+ return end;
} else {
zeroWordsToFill = 8 - colonCount;
}
@@ -183,18 +194,13 @@ bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
int pos = 0;
while (pos < 15) {
- const char *endptr;
- bool ok;
- quint64 ll = qstrtoull(ptr, &endptr, 16, &ok);
- quint16 x = ll;
-
- if (ptr == endptr) {
+ if (*ptr == ':') {
// empty field, we hope it's "::"
if (zeroWordsToFill < 1)
- return false;
+ return begin + (ptr - buffer.data());
if (pos == 0 || pos == colonCount * 2) {
if (ptr[0] == '\0' || ptr[1] != ':')
- return false;
+ return begin + (ptr - buffer.data());
++ptr;
}
pos += zeroWordsToFill * 2;
@@ -202,24 +208,30 @@ bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
++ptr;
continue;
}
+
+ const char *endptr;
+ bool ok;
+ quint64 ll = qstrtoull(ptr, &endptr, 16, &ok);
+ quint16 x = ll;
+
if (!ok || ll != x)
- return false;
+ return begin + (ptr - buffer.data());
if (*endptr == '.') {
// this could be an IPv4 address
// it's only valid in the last element
if (pos != 12)
- return false;
+ return begin + (ptr - buffer.data());
IPv4Address ip4;
if (!parseIp4Internal(ip4, ptr, false))
- return false;
+ return begin + (ptr - buffer.data());
address[12] = ip4 >> 24;
address[13] = ip4 >> 16;
address[14] = ip4 >> 8;
address[15] = ip4;
- return true;
+ return 0;
}
address[pos++] = x >> 8;
@@ -228,10 +240,10 @@ bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end)
if (*endptr == '\0')
break;
if (*endptr != ':')
- return false;
+ return begin + (endptr - buffer.data());
ptr = endptr + 1;
}
- return pos == 16;
+ return pos == 16 ? 0 : end;
}
static inline QChar toHex(uchar c)
diff --git a/src/corelib/io/qipaddress_p.h b/src/corelib/io/qipaddress_p.h
index d5c158d4d1..3059a1c205 100644
--- a/src/corelib/io/qipaddress_p.h
+++ b/src/corelib/io/qipaddress_p.h
@@ -63,7 +63,7 @@ typedef quint32 IPv4Address;
typedef quint8 IPv6Address[16];
Q_CORE_EXPORT bool parseIp4(IPv4Address &address, const QChar *begin, const QChar *end);
-Q_CORE_EXPORT bool parseIp6(IPv6Address &address, const QChar *begin, const QChar *end);
+Q_CORE_EXPORT const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end);
Q_CORE_EXPORT void toString(QString &appendTo, IPv4Address address);
Q_CORE_EXPORT void toString(QString &appendTo, IPv6Address address);
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 30320c9cc2..d7729b7cb9 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -1141,7 +1141,8 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
static bool parseIp6(QString &host, const QChar *begin, const QChar *end, QUrl::ParsingMode mode)
{
QIPAddressUtils::IPv6Address address;
- if (!QIPAddressUtils::parseIp6(address, begin, end)) {
+ const QChar *ret = QIPAddressUtils::parseIp6(address, begin, end);
+ if (ret) {
// this struct is kept in automatic storage because it's only 4 bytes
const ushort decodeColon[] = { decode(':'), 0 };
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index dc67b0d835..5ef428305c 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -189,7 +189,7 @@ static bool parseIp6(const QString &address, QIPAddressUtils::IPv6Address &addr,
} else {
scopeId->clear();
}
- return QIPAddressUtils::parseIp6(addr, tmp.constBegin(), tmp.constEnd());
+ return QIPAddressUtils::parseIp6(addr, tmp.constBegin(), tmp.constEnd()) == 0;
}
bool QHostAddressPrivate::parse()