From bb220f2d99261eaa7c5021988a9443735ed2a93d Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 15 Oct 2021 12:37:33 +0200 Subject: [PATCH] Fix overflow issue on parsing min-qint64 with its minus sign repeated The call to std::from_chars() accepts a sign, but we've already dealt with a sign, so that would be a second sign. Check the first character after any prefix is in fact a digit (for the base in use). This is a follow-up to commit 5644af6f8a800a1516360a42ba4c1a8dc61fc516. Fixes: QTBUG-97521 Change-Id: I65fb144bf6a8430da90ec5f65088ca20e79bf02f Reviewed-by: Thiago Macieira --- src/corelib/text/qlocale_tools.cpp | 17 ++++++++++++++++- .../tst_qstringapisymmetry.cpp | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/corelib/text/qlocale_tools.cpp b/src/corelib/text/qlocale_tools.cpp index 18dd24daf1..c133a028c0 100644 --- a/src/corelib/text/qlocale_tools.cpp +++ b/src/corelib/text/qlocale_tools.cpp @@ -437,6 +437,19 @@ static auto scanPrefix(const char *p, const char *stop, int base) return R{p, base}; } +static bool isDigitForBase(char d, int base) +{ + if (d < '0') + return false; + if (d - '0' < qMin(base, 10)) + return true; + if (base > 10) { + d |= 0x20; // tolower + return d >= 'a' && d < 'a' + base - 10; + } + return false; +} + unsigned long long qstrntoull(const char *begin, qsizetype size, const char **endptr, int base, bool *ok) { @@ -479,7 +492,9 @@ qstrntoll(const char *begin, qsizetype size, const char **endptr, int base, bool ++p; const auto prefix = scanPrefix(p, stop, base); - if (!prefix.base || prefix.next >= stop) { + // Must check for digit, as from_chars() will accept a sign, which would be + // a second sign, that we should reject. + if (!prefix.base || prefix.next >= stop || !isDigitForBase(*prefix.next, prefix.base)) { if (endptr) *endptr = begin; *ok = false; diff --git a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp index 543449c5e6..a64811cea4 100644 --- a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp +++ b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp @@ -2080,6 +2080,7 @@ void tst_QStringApiSymmetry::toNumber_data() QTest::addRow("-32768") << QString::fromUtf8("-32768") << qint64(-32768) << true; QTest::addRow("100x") << QString::fromUtf8("100x") << qint64(0) << false; QTest::addRow("-100x") << QString::fromUtf8("-100x") << qint64(0) << false; + QTest::addRow("-min64") << QString::fromUtf8("--9223372036854775808") << qint64(0) << false; } template