QLocale: Return overflowing numbers from asciiToDouble()
The behavior from before libdouble-conversion is that in case of an overflow the OK flag is set to false, but the returned number is still infinity, rather than 0. Also, the number of processed characters is always set to the number of characters actually processed, unless garbage is found. There is an important distinction between an overflow and garbage. The client code may accept overflows and infinity may be a valid result. Garbage is most certainly not acceptable. Having an infinity/false result in addition to 0/false allows the client code to distinguish those. One application where this is useful is parsing JavaScript. Change-Id: I4b8581568144b44fca3353c4bd9685c702762af9 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
a926f675be
commit
59dbf1786f
@ -303,31 +303,51 @@ double asciiToDouble(const char *num, int numLen, bool &ok, int &processed)
|
|||||||
d = conv.StringToDouble(num, numLen, &processed);
|
d = conv.StringToDouble(num, numLen, &processed);
|
||||||
|
|
||||||
if (!qIsFinite(d)) {
|
if (!qIsFinite(d)) {
|
||||||
processed = 0;
|
|
||||||
ok = false;
|
ok = false;
|
||||||
return 0.0;
|
if (qIsNaN(d)) {
|
||||||
|
// Garbage found. We don't accept it and return 0.
|
||||||
|
processed = 0;
|
||||||
|
return 0.0;
|
||||||
|
} else {
|
||||||
|
// Overflow. That's not OK, but we still return infinity.
|
||||||
|
return d;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT(processed == numLen); // Otherwise we would have gotten NaN
|
|
||||||
#else
|
#else
|
||||||
if (qDoubleSscanf(num, QT_CLOCALE, "%lf%n", &d, &processed) < 1)
|
if (qDoubleSscanf(num, QT_CLOCALE, "%lf%n", &d, &processed) < 1)
|
||||||
processed = 0;
|
processed = 0;
|
||||||
|
|
||||||
if (processed != numLen || !qIsFinite(d)) {
|
if (processed != numLen || qIsNaN(d)) {
|
||||||
// We stopped at a non-digit character after converting some digits
|
// Implementation defined nan symbol or garbage found. We don't accept it.
|
||||||
// or we found an implementation-defined symbol for infinity or nan, which we don't accept.
|
|
||||||
processed = 0;
|
processed = 0;
|
||||||
ok = false;
|
ok = false;
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!qIsFinite(d)) {
|
||||||
|
// Overflow. Check for implementation-defined infinity symbols and reject them.
|
||||||
|
// We assume that any infinity symbol has to contain a character that cannot be part of a
|
||||||
|
// "normal" number (that is 0-9, ., -, +, e).
|
||||||
|
ok = false;
|
||||||
|
for (int i = 0; i < numLen; ++i) {
|
||||||
|
char c = num[i];
|
||||||
|
if ((c < '0' || c > '9') && c != '.' && c != '-' && c != '+' && c != 'e') {
|
||||||
|
// Garbage found
|
||||||
|
processed = 0;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
#endif // !defined(QT_NO_DOUBLECONVERSION) && !defined(QT_BOOTSTRAPPED)
|
#endif // !defined(QT_NO_DOUBLECONVERSION) && !defined(QT_BOOTSTRAPPED)
|
||||||
|
|
||||||
|
Q_ASSERT(processed == numLen); // Otherwise we would have gotten NaN or sorted it out above.
|
||||||
|
|
||||||
// Check if underflow has occurred.
|
// Check if underflow has occurred.
|
||||||
if (isZero(d)) {
|
if (isZero(d)) {
|
||||||
for (int i = 0; i < numLen; ++i) {
|
for (int i = 0; i < numLen; ++i) {
|
||||||
if (num[i] >= '1' && num[i] <= '9') {
|
if (num[i] >= '1' && num[i] <= '9') {
|
||||||
// if a digit before any 'e' is not 0, then a non-zero number was intended.
|
// if a digit before any 'e' is not 0, then a non-zero number was intended.
|
||||||
processed = 0;
|
|
||||||
ok = false;
|
ok = false;
|
||||||
return 0.0;
|
return 0.0;
|
||||||
} else if (num[i] == 'e') {
|
} else if (num[i] == 'e') {
|
||||||
|
@ -1931,13 +1931,13 @@ a(QLatin1String("0.0000000000000000000000000000000000000000000000000000000000000
|
|||||||
ok = false;
|
ok = false;
|
||||||
d = a.toDouble(&ok);
|
d = a.toDouble(&ok);
|
||||||
QVERIFY(!ok); // detectable overflow
|
QVERIFY(!ok); // detectable overflow
|
||||||
QCOMPARE(d, 0.0);
|
QVERIFY(qIsInf(d));
|
||||||
|
|
||||||
a = QLatin1String("-1e600");
|
a = QLatin1String("-1e600");
|
||||||
ok = false;
|
ok = false;
|
||||||
d = a.toDouble(&ok);
|
d = a.toDouble(&ok);
|
||||||
QVERIFY(!ok); // detectable underflow
|
QVERIFY(!ok); // detectable underflow
|
||||||
QCOMPARE(d, 0.0);
|
QVERIFY(qIsInf(-d));
|
||||||
|
|
||||||
a = QLatin1String("1e-600");
|
a = QLatin1String("1e-600");
|
||||||
ok = false;
|
ok = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user