diff options
-rw-r--r-- | src/corelib/global/qglobal.cpp | 22 | ||||
-rw-r--r-- | src/corelib/tools/qbytearray.cpp | 3 | ||||
-rw-r--r-- | src/corelib/tools/qlocale.cpp | 18 | ||||
-rw-r--r-- | src/corelib/tools/qlocale_tools.cpp | 16 | ||||
-rw-r--r-- | src/corelib/tools/qlocale_tools_p.h | 7 | ||||
-rw-r--r-- | tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp | 6 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp | 44 |
7 files changed, 102 insertions, 14 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 3fe91cae65..b52139d5a6 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -3442,7 +3442,27 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT bool ok_ = true; const char *endptr; const qlonglong value = qstrtoll(buffer, &endptr, 0, &ok_); - if (int(value) != value || *endptr != '\0') { // this is the check in QByteArray::toInt(), keep it in sync + + // Keep the following checks in sync with QByteArray::toInt() + if (!ok_) { + if (ok) + *ok = false; + return 0; + } + + if (*endptr != '\0') { + while (ascii_isspace(*endptr)) + ++endptr; + } + + if (*endptr != '\0') { + // we stopped at a non-digit character after converting some digits + if (ok) + *ok = false; + return 0; + } + + if (int(value) != value) { if (ok) *ok = false; return 0; diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index d8d8be7a26..3a24176dc2 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -4135,7 +4135,8 @@ double QByteArray::toDouble(bool *ok) const QByteArray nulled = nulTerminated(); bool nonNullOk = false; int processed = 0; - double d = asciiToDouble(nulled.constData(), nulled.length(), nonNullOk, processed); + double d = asciiToDouble(nulled.constData(), nulled.length(), + nonNullOk, processed, WhitespacesAllowed); if (ok) *ok = nonNullOk; return d; diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index e70630eb12..3997652437 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -3646,6 +3646,11 @@ qlonglong QLocaleData::bytearrayToLongLong(const char *num, int base, bool *ok) } if (*endptr != '\0') { + while (ascii_isspace(*endptr)) + ++endptr; + } + + if (*endptr != '\0') { // we stopped at a non-digit character after converting some digits if (ok != 0) *ok = false; @@ -3663,12 +3668,23 @@ qulonglong QLocaleData::bytearrayToUnsLongLong(const char *num, int base, bool * const char *endptr; qulonglong l = qstrtoull(num, &endptr, base, &_ok); - if (!_ok || *endptr != '\0') { + if (!_ok) { if (ok != 0) *ok = false; return 0; } + if (*endptr != '\0') { + while (ascii_isspace(*endptr)) + ++endptr; + } + + if (*endptr != '\0') { + if (ok != nullptr) + *ok = false; + return 0; + } + if (ok != 0) *ok = true; return l; diff --git a/src/corelib/tools/qlocale_tools.cpp b/src/corelib/tools/qlocale_tools.cpp index 4d969a4723..baa4da37f4 100644 --- a/src/corelib/tools/qlocale_tools.cpp +++ b/src/corelib/tools/qlocale_tools.cpp @@ -278,7 +278,7 @@ void doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char * } double asciiToDouble(const char *num, int numLen, bool &ok, int &processed, - TrailingJunkMode trailingJunkMode) + StrayCharacterMode strayCharMode) { if (*num == '\0') { ok = false; @@ -315,9 +315,13 @@ double asciiToDouble(const char *num, int numLen, bool &ok, int &processed, double d = 0.0; #if !defined(QT_NO_DOUBLECONVERSION) && !defined(QT_BOOTSTRAPPED) - int conv_flags = (trailingJunkMode == TrailingJunkAllowed) ? - double_conversion::StringToDoubleConverter::ALLOW_TRAILING_JUNK : - double_conversion::StringToDoubleConverter::NO_FLAGS; + int conv_flags = double_conversion::StringToDoubleConverter::NO_FLAGS; + if (strayCharMode == TrailingJunkAllowed) { + conv_flags = double_conversion::StringToDoubleConverter::ALLOW_TRAILING_JUNK; + } else if (strayCharMode == WhitespacesAllowed) { + conv_flags = double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES + | double_conversion::StringToDoubleConverter::ALLOW_TRAILING_SPACES; + } double_conversion::StringToDoubleConverter conv(conv_flags, 0.0, qt_snan(), 0, 0); d = conv.StringToDouble(num, numLen, &processed); @@ -336,7 +340,7 @@ double asciiToDouble(const char *num, int numLen, bool &ok, int &processed, if (qDoubleSscanf(num, QT_CLOCALE, "%lf%n", &d, &processed) < 1) processed = 0; - if ((trailingJunkMode == TrailingJunkProhibited && processed != numLen) || qIsNaN(d)) { + if ((strayCharMode == TrailingJunkProhibited && processed != numLen) || qIsNaN(d)) { // Implementation defined nan symbol or garbage found. We don't accept it. processed = 0; ok = false; @@ -361,7 +365,7 @@ double asciiToDouble(const char *num, int numLen, bool &ok, int &processed, #endif // !defined(QT_NO_DOUBLECONVERSION) && !defined(QT_BOOTSTRAPPED) // Otherwise we would have gotten NaN or sorted it out above. - Q_ASSERT(trailingJunkMode == TrailingJunkAllowed || processed == numLen); + Q_ASSERT(strayCharMode == TrailingJunkAllowed || processed == numLen); // Check if underflow has occurred. if (isZero(d)) { diff --git a/src/corelib/tools/qlocale_tools_p.h b/src/corelib/tools/qlocale_tools_p.h index 742abb4957..c8ea25b504 100644 --- a/src/corelib/tools/qlocale_tools_p.h +++ b/src/corelib/tools/qlocale_tools_p.h @@ -72,13 +72,14 @@ QT_BEGIN_NAMESPACE -enum TrailingJunkMode { +enum StrayCharacterMode { TrailingJunkProhibited, - TrailingJunkAllowed + TrailingJunkAllowed, + WhitespacesAllowed }; double asciiToDouble(const char *num, int numLen, bool &ok, int &processed, - TrailingJunkMode trailingJunkMode = TrailingJunkProhibited); + StrayCharacterMode strayCharMode = TrailingJunkProhibited); void doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char *buf, int bufSize, bool &sign, int &length, int &decpt); diff --git a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp index f02e902468..544cb1bf07 100644 --- a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp +++ b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp @@ -160,8 +160,10 @@ void tst_QGetPutEnv::intValue_data() // some repetition from what is tested in getSetCheck() QTest::newRow("empty") << QByteArray() << 0 << false; - QTest::newRow("spaces-heading") << QByteArray(" 1") << 1 << true; - QTest::newRow("spaces-trailing") << QByteArray("1 ") << 0 << false; + QTest::newRow("spaces-heading") << QByteArray(" \n\r\t1") << 1 << true; + QTest::newRow("spaces-trailing") << QByteArray("1 \n\r\t") << 1 << true; + QTest::newRow("junk-heading") << QByteArray("x1") << 0 << false; + QTest::newRow("junk-trailing") << QByteArray("1x") << 0 << false; #define ROW(x, i, b) \ QTest::newRow(#x) << QByteArray(#x) << (i) << (b) diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp index ecfa331141..1ed41793dc 100644 --- a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp @@ -106,6 +106,8 @@ private slots: void number(); void toInt_data(); void toInt(); + void toDouble_data(); + void toDouble(); void blockSizeCalculations(); void resizeAfterFromRawData(); @@ -1317,6 +1319,11 @@ void tst_QByteArray::toInt_data() QTest::newRow("base 0-3") << QByteArray("010") << 0 << int(8) << true; QTest::newRow("empty") << QByteArray() << 0 << int(0) << false; + QTest::newRow("leading space") << QByteArray(" 100") << 10 << int(100) << true; + QTest::newRow("trailing space") << QByteArray("100 ") << 10 << int(100) << true; + QTest::newRow("leading junk") << QByteArray("x100") << 10 << int(0) << false; + QTest::newRow("trailing junk") << QByteArray("100x") << 10 << int(0) << false; + // using fromRawData QTest::newRow("raw1") << QByteArray::fromRawData("1", 1) << 10 << 1 << true; QTest::newRow("raw2") << QByteArray::fromRawData("1foo", 1) << 10 << 1 << true; @@ -1341,6 +1348,34 @@ void tst_QByteArray::toInt() QCOMPARE( number, expectednumber ); } +void tst_QByteArray::toDouble_data() +{ + QTest::addColumn<QByteArray>("string"); + QTest::addColumn<double>("expectedNumber"); + QTest::addColumn<bool>("expectedOk"); + + QTest::newRow("decimal") << QByteArray("1.2345") << 1.2345 << true; + QTest::newRow("exponent lowercase") << QByteArray("1.2345e+01") << 12.345 << true; + QTest::newRow("exponent uppercase") << QByteArray("1.2345E+02") << 123.45 << true; + QTest::newRow("leading spaces") << QByteArray(" \n\r\t1.2345") << 1.2345 << true; + QTest::newRow("trailing spaces") << QByteArray("1.2345 \n\r\t") << 1.2345 << true; + QTest::newRow("leading junk") << QByteArray("x1.2345") << 0.0 << false; + QTest::newRow("trailing junk") << QByteArray("1.2345x") << 0.0 << false; +} + +void tst_QByteArray::toDouble() +{ + QFETCH(QByteArray, string); + QFETCH(double, expectedNumber); + QFETCH(bool, expectedOk); + + bool ok; + const double number = string.toDouble(&ok); + + QCOMPARE(ok, expectedOk); + QCOMPARE(number, expectedNumber); +} + void tst_QByteArray::toULong_data() { QTest::addColumn<QByteArray>("str"); @@ -1354,6 +1389,11 @@ void tst_QByteArray::toULong_data() QTest::newRow("empty") << QByteArray("") << 10 << 0UL << false; QTest::newRow("ulong1") << QByteArray("3234567890") << 10 << 3234567890UL << true; QTest::newRow("ulong2") << QByteArray("fFFfFfFf") << 16 << 0xFFFFFFFFUL << true; + + QTest::newRow("leading spaces") << QByteArray(" \n\r\t100") << 10 << 100UL << true; + QTest::newRow("trailing spaces") << QByteArray("100 \n\r\t") << 10 << 100UL << true; + QTest::newRow("leading junk") << QByteArray("x100") << 10 << 0UL << false; + QTest::newRow("trailing junk") << QByteArray("100x") << 10 << 0UL << false; } void tst_QByteArray::toULong() @@ -1379,6 +1419,10 @@ void tst_QByteArray::toULongLong_data() QTest::newRow("default") << QByteArray() << 10 << (qulonglong)0 << false; QTest::newRow("out of base bound") << QByteArray("c") << 10 << (qulonglong)0 << false; + QTest::newRow("leading spaces") << QByteArray(" \n\r\t100") << 10 << qulonglong(100) << true; + QTest::newRow("trailing spaces") << QByteArray("100 \n\r\t") << 10 << qulonglong(100) << true; + QTest::newRow("leading junk") << QByteArray("x100") << 10 << qulonglong(0) << false; + QTest::newRow("trailing junk") << QByteArray("100x") << 10 << qulonglong(0) << false; } void tst_QByteArray::toULongLong() |