From 9063119268821a5ea5c1fec0156efa72b84752c6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 1 Jul 2013 18:24:40 -0700 Subject: Make QIPAddress::parseIp6 return the first bad character In case of undetermined error, returns end. Change-Id: Ic5d16bab5fc56ad24f19da25f73f9b844ce11d3f Reviewed-by: David Faure (KDE) --- src/corelib/io/qipaddress.cpp | 60 ++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 24 deletions(-) (limited to 'src/corelib/io/qipaddress.cpp') 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 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(begin); const ushort *const uend = reinterpret_cast(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(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) -- cgit v1.2.3