QTextStream: fix UB calls to qAbs() with minimal arguments

QTextStream's operator<<(number) uses qAbs to extract the "absolute
value" of number, and passes that and the number's sign to an internal
formatting function. However qAbs is unsuitable for the task, because it
will fail if `number` is minimal, as it returns the same type of
its input.

Since we can afford to change the type of the result, call the private
qUnsignedAbs() function instead.

Change-Id: Ib813a199503f2d07c78bb76862ab2e15d68d0ec2
Pick-to: 6.8
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 8f762b546fe6b2254029c4804a32d9ae6bbf4495)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Giuseppe D'Angelo 2025-01-27 21:32:42 +01:00 committed by Qt Cherry-pick Bot
parent 0479ef1c1c
commit b50f026c55
2 changed files with 7 additions and 4 deletions

View File

@ -2294,7 +2294,7 @@ QTextStream &QTextStream::operator<<(signed short i)
{
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
d->putNumber((qulonglong)qAbs(qlonglong(i)), i < 0);
d->putNumber(QtPrivate::qUnsignedAbs(i), i < 0);
return *this;
}
@ -2320,7 +2320,7 @@ QTextStream &QTextStream::operator<<(signed int i)
{
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
d->putNumber((qulonglong)qAbs(qlonglong(i)), i < 0);
d->putNumber(QtPrivate::qUnsignedAbs(i), i < 0);
return *this;
}
@ -2346,7 +2346,7 @@ QTextStream &QTextStream::operator<<(signed long i)
{
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
d->putNumber((qulonglong)qAbs(qlonglong(i)), i < 0);
d->putNumber(QtPrivate::qUnsignedAbs(i), i < 0);
return *this;
}
@ -2372,7 +2372,7 @@ QTextStream &QTextStream::operator<<(qlonglong i)
{
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
d->putNumber((qulonglong)qAbs(i), i < 0);
d->putNumber(QtPrivate::qUnsignedAbs(i), i < 0);
return *this;
}

View File

@ -2278,6 +2278,7 @@ void tst_QTextStream::signedShort_write_operator_ToDevice_data()
QTest::newRow("65535") << Q_UINT64_C(65535) << QByteArray("-1") << QByteArray("-1");
QTest::newRow("65536") << Q_UINT64_C(65536) << QByteArray("0") << QByteArray("0");
QTest::newRow("65537") << Q_UINT64_C(65537) << QByteArray("1") << QByteArray("1");
QTest::newRow("-32768") << quint64(-32768) << QByteArray("-32768") << QByteArray("-32,768");
}
IMPLEMENT_STREAM_LEFT_INT_OPERATOR_TEST(signedShort, signed short)
;
@ -2324,6 +2325,7 @@ void tst_QTextStream::signedInt_write_operator_ToDevice_data()
QTest::newRow("4294967295") << Q_UINT64_C(4294967295) << QByteArray("-1") << QByteArray("-1");
QTest::newRow("4294967296") << Q_UINT64_C(4294967296) << QByteArray("0") << QByteArray("0");
QTest::newRow("4294967297") << Q_UINT64_C(4294967297) << QByteArray("1") << QByteArray("1");
QTest::newRow("-2147483648") << quint64(-2147483648) << QByteArray("-2147483648") << QByteArray("-2,147,483,648");
}
IMPLEMENT_STREAM_LEFT_INT_OPERATOR_TEST(signedInt, signed int)
;
@ -2380,6 +2382,7 @@ void tst_QTextStream::qlonglong_write_operator_ToDevice_data()
QTest::newRow("9223372036854775808") << Q_UINT64_C(9223372036854775808) << QByteArray("-9223372036854775808") << QByteArray("-9,223,372,036,854,775,808");
QTest::newRow("9223372036854775809") << Q_UINT64_C(9223372036854775809) << QByteArray("-9223372036854775807") << QByteArray("-9,223,372,036,854,775,807");
QTest::newRow("18446744073709551615") << Q_UINT64_C(18446744073709551615) << QByteArray("-1") << QByteArray("-1");
QTest::newRow("-9223372036854775808") << quint64(Q_INT64_C(-9223372036854775807) - 1) << QByteArray("-9223372036854775808") << QByteArray("-9,223,372,036,854,775,808");
}
IMPLEMENT_STREAM_LEFT_INT_OPERATOR_TEST(qlonglong, qlonglong)
;