From a2ef00ee82d011560717b9ec8a9f7b381da95a4a Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 27 Jan 2025 21:32:42 +0100 Subject: [PATCH] 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 Reviewed-by: Thiago Macieira (cherry picked from commit 8f762b546fe6b2254029c4804a32d9ae6bbf4495) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit b50f026c5586bb31d0611ca570a40e77d5e4eb43) --- src/corelib/serialization/qtextstream.cpp | 8 ++++---- .../corelib/serialization/qtextstream/tst_qtextstream.cpp | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp index d82bb61337..6aed1c418e 100644 --- a/src/corelib/serialization/qtextstream.cpp +++ b/src/corelib/serialization/qtextstream.cpp @@ -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; } diff --git a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp index 411084a36c..188b4542a1 100644 --- a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp +++ b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp @@ -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) ;