Fix parsing of 0E+1 and 0E-1 (capital 'E')

Since the result is an actual zero, this section of code looking for
underflows kicks in. But we forgot to take the capital letter into
account when parsing the number.

Task-number: QTBUG-61350
Change-Id: Ia53158e207a94bf49489fffd14c6abbd21f0bac0
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
bb10
Thiago Macieira 2017-06-09 22:32:34 -07:00
parent c854fc5a6b
commit 8616b2112c
2 changed files with 58 additions and 2 deletions

View File

@ -370,7 +370,7 @@ double asciiToDouble(const char *num, int numLen, bool &ok, int &processed,
// if a digit before any 'e' is not 0, then a non-zero number was intended.
ok = false;
return 0.0;
} else if (num[i] == 'e') {
} else if (num[i] == 'e' || num[i] == 'E') {
break;
}
}

View File

@ -920,6 +920,18 @@ void tst_QLocale::strtod_data()
QTest::addColumn<int>("processed");
QTest::addColumn<bool>("ok");
// plain numbers, success
QTest::newRow("0") << QString("0") << 0.0 << 1 << true;
QTest::newRow("0.") << QString("0.") << 0.0 << 2 << true;
QTest::newRow("0.0") << QString("0.0") << 0.0 << 3 << true;
QTest::newRow("0e+0") << QString("0e+0") << 0.0 << 4 << true;
QTest::newRow("0e-0") << QString("0e-0") << 0.0 << 4 << true;
QTest::newRow("0e+1") << QString("0e+1") << 0.0 << 4 << true;
QTest::newRow("0e-1") << QString("0e-1") << 0.0 << 4 << true;
QTest::newRow("0E+0") << QString("0E+0") << 0.0 << 4 << true;
QTest::newRow("0E-0") << QString("0E-0") << 0.0 << 4 << true;
QTest::newRow("0E+1") << QString("0E+1") << 0.0 << 4 << true;
QTest::newRow("0E-1") << QString("0E-1") << 0.0 << 4 << true;
QTest::newRow("3.4") << QString("3.4") << 3.4 << 3 << true;
QTest::newRow("0.035003945") << QString("0.035003945") << 0.035003945 << 11 << true;
QTest::newRow("3.5003945e-2") << QString("3.5003945e-2") << 0.035003945 << 12 << true;
@ -928,6 +940,10 @@ void tst_QLocale::strtod_data()
QTest::newRow("12456789012") << QString("12456789012") << 12456789012.0 << 11 << true;
QTest::newRow("1.2456789012e10") << QString("1.2456789012e10") << 12456789012.0 << 15 << true;
// starts with junk, fails
QTest::newRow("a0") << QString("a0") << 0.0 << 0 << false;
QTest::newRow("a0.") << QString("a0.") << 0.0 << 0 << false;
QTest::newRow("a0.0") << QString("a0.0") << 0.0 << 0 << false;
QTest::newRow("a3.4") << QString("a3.4") << 0.0 << 0 << false;
QTest::newRow("b0.035003945") << QString("b0.035003945") << 0.0 << 0 << false;
QTest::newRow("c3.5003945e-2") << QString("c3.5003945e-2") << 0.0 << 0 << false;
@ -936,7 +952,18 @@ void tst_QLocale::strtod_data()
QTest::newRow("f12456789012") << QString("f12456789012") << 0.0 << 0 << false;
QTest::newRow("g1.2456789012e10") << QString("g1.2456789012e10") << 0.0 << 0 << false;
QTest::newRow("3.4a") << QString("3.4a") << 3.4 << 3 << true;
// ends with junk, success
QTest::newRow("0a") << QString("0a") << 0.0 << 1 << true;
QTest::newRow("0.a") << QString("0.a") << 0.0 << 2 << true;
QTest::newRow("0.0a") << QString("0.0a") << 0.0 << 3 << true;
QTest::newRow("0e+0a") << QString("0e+0a") << 0.0 << 4 << true;
QTest::newRow("0e-0a") << QString("0e-0a") << 0.0 << 4 << true;
QTest::newRow("0e+1a") << QString("0e+1a") << 0.0 << 4 << true;
QTest::newRow("0e-1a") << QString("0e-1a") << 0.0 << 4 << true;
QTest::newRow("0E+0a") << QString("0E+0a") << 0.0 << 4 << true;
QTest::newRow("0E-0a") << QString("0E-0a") << 0.0 << 4 << true;
QTest::newRow("0E+1a") << QString("0E+1a") << 0.0 << 4 << true;
QTest::newRow("0E-1a") << QString("0E-1a") << 0.0 << 4 << true;
QTest::newRow("0.035003945b") << QString("0.035003945b") << 0.035003945 << 11 << true;
QTest::newRow("3.5003945e-2c") << QString("3.5003945e-2c") << 0.035003945 << 12 << true;
QTest::newRow("0.000003945d") << QString("0.000003945d") << 0.000003945 << 11 << true;
@ -944,6 +971,10 @@ void tst_QLocale::strtod_data()
QTest::newRow("12456789012f") << QString("12456789012f") << 12456789012.0 << 11 << true;
QTest::newRow("1.2456789012e10g") << QString("1.2456789012e10g") << 12456789012.0 << 15 << true;
// "0x" prefix, success but only for the "0" before "x"
QTest::newRow("0x0") << QString("0x0") << 0.0 << 1 << true;
QTest::newRow("0x0.") << QString("0x0.") << 0.0 << 1 << true;
QTest::newRow("0x0.0") << QString("0x0.0") << 0.0 << 1 << true;
QTest::newRow("0x3.4") << QString("0x3.4") << 0.0 << 1 << true;
QTest::newRow("0x0.035003945") << QString("0x0.035003945") << 0.0 << 1 << true;
QTest::newRow("0x3.5003945e-2") << QString("0x3.5003945e-2") << 0.0 << 1 << true;
@ -951,6 +982,9 @@ void tst_QLocale::strtod_data()
QTest::newRow("0x3.945e-6") << QString("0x3.945e-6") << 0.0 << 1 << true;
QTest::newRow("0x12456789012") << QString("0x12456789012") << 0.0 << 1 << true;
QTest::newRow("0x1.2456789012e10") << QString("0x1.2456789012e10") << 0.0 << 1 << true;
// hexfloat is not supported (yet)
QTest::newRow("0x1.921fb5p+1") << QString("0x1.921fb5p+1") << 0.0 << 1 << true;
}
void tst_QLocale::strtod()
@ -968,6 +1002,28 @@ void tst_QLocale::strtod()
QCOMPARE(result, num);
QCOMPARE(actualOk, ok);
QCOMPARE(static_cast<int>(end - numData.constData()), processed);
// make sure neither QByteArray, QString or QLocale also work
// (but they don't support incomplete parsing)
if (processed == num_str.size() || processed == 0) {
actualOk = false;
QCOMPARE(num_str.toDouble(&actualOk), num);
QCOMPARE(actualOk, ok);
actualOk = false;
QCOMPARE(numData.toDouble(&actualOk), num);
QCOMPARE(actualOk, ok);
actualOk = false;
QCOMPARE(QLocale::c().toDouble(num_str, &actualOk), num);
QCOMPARE(actualOk, ok);
}
// and QStringRef, but we can limit the length without allocating memory
QStringRef num_strref(&num_str, 0, processed);
actualOk = false;
QCOMPARE(QLocale::c().toDouble(num_strref, &actualOk), num);
QCOMPARE(actualOk, ok);
}
void tst_QLocale::long_long_conversion_data()