QVersionNumber: correctly fail for numerically very large segments

The result of qstrtoull() was unconditionally truncated to an int,
resulting in wrong values being appended to the segments vector
when the numerical segment value was above INT_MAX.

Prevent this by first checking the return value of qstrtoull
as a qulonglong for values larger than INT_MAX and stopping
processing in that case. That means that segments that
numerically overflow an int are now considered part of the
suffix.

Also added tests for the case where a segment value is larger
than ULLONG_MAX. That was already working correctly.

Change-Id: Ia4b89021dcfe6bfae27c8d89bb678ec5e0e3b847
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2014-09-03 14:17:07 +02:00
parent 42d4e054a6
commit 1ce6e432b6
2 changed files with 21 additions and 4 deletions

View File

@ -54,6 +54,7 @@
#endif
#include <algorithm>
#include <limits>
QT_BEGIN_NAMESPACE
@ -390,14 +391,13 @@ QVersionNumber QVersionNumber::fromString(const QString &string, int *suffixInde
const char *end = start;
const char *lastGoodEnd = start;
const char *endOfString = cString.constData() + cString.size();
int value;
do {
bool ok = false;
value = int(qstrtoull(start, &end, 10, &ok));
if (!ok)
const qulonglong value = qstrtoull(start, &end, 10, &ok);
if (!ok || value > qulonglong(std::numeric_limits<int>::max()))
break;
seg.append(value);
seg.append(int(value));
start = end + 1;
lastGoodEnd = end;
} while (start < endOfString && (end < endOfString && *end == '.'));

View File

@ -435,6 +435,23 @@ void tst_QVersionNumber::assignment()
void tst_QVersionNumber::fromString_data()
{
singleInstanceData();
const quint64 largerThanIntCanHold = quint64(std::numeric_limits<int>::max()) + 1;
const QString largerThanIntCanHoldString0 = QString::number(largerThanIntCanHold) + ".0";
const QString largerThanIntCanHoldString1 = "0." + QString::number(largerThanIntCanHold);
QTest::newRow(qPrintable(largerThanIntCanHoldString0))
<< QVector<int>() << QVersionNumber() << QString() << largerThanIntCanHoldString0 << 0 << true;
QTest::newRow(qPrintable(largerThanIntCanHoldString1))
<< QVector<int>(0) << QVersionNumber(0) << QStringLiteral("0") << largerThanIntCanHoldString1 << 1 << true;
const QString largerThanULongLongCanHoldString0 = QString::number(std::numeric_limits<qulonglong>::max()) + "0.0"; // 10x ULLONG_MAX
const QString largerThanULongLongCanHoldString1 = "0." + QString::number(std::numeric_limits<qulonglong>::max()) + '0'; // 10x ULLONG_MAX
QTest::newRow(qPrintable(largerThanULongLongCanHoldString0))
<< QVector<int>() << QVersionNumber() << QString() << largerThanULongLongCanHoldString0 << 0 << true;
QTest::newRow(qPrintable(largerThanULongLongCanHoldString1))
<< QVector<int>(0) << QVersionNumber(0) << QStringLiteral("0") << largerThanULongLongCanHoldString1 << 1 << true;
}
void tst_QVersionNumber::fromString()