From 8232c837b02885b6e143e6982bda3ef19e4017fa Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 27 Jan 2025 17:36:28 +0100 Subject: [PATCH] QDebug: do not trigger integer overflow when printing a QRect QRect::width() and height() may overflow: they're only safe to call when right-left+1 (or bottom-top+1) is representable by an `int`. Therefore, avoiding calling them from QDebug, which is supposed to "always work" (otherwise, it's not of great debugging help...). QRectF does not have this issue as it stores the width directly. Change-Id: I438dbacae42c17730afb92f05d16e3eebb161255 Pick-to: 6.8 6.5 Reviewed-by: Thiago Macieira (cherry picked from commit 0f336500a0add3e3a8bb31c5cc605e5e13e23833) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/io/qdebug_p.h | 12 +++++++- tests/auto/corelib/tools/qrect/tst_qrect.cpp | 30 ++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/qdebug_p.h b/src/corelib/io/qdebug_p.h index 810fc3b4b65..9b048ae9ab9 100644 --- a/src/corelib/io/qdebug_p.h +++ b/src/corelib/io/qdebug_p.h @@ -23,6 +23,8 @@ QT_BEGIN_NAMESPACE +class QRect; + namespace QtDebugUtils { Q_CORE_EXPORT QByteArray toPrintable(const char *data, qint64 len, qsizetype maxSize); @@ -44,7 +46,15 @@ static inline void formatQSize(QDebug &debug, const Size &size) template static inline void formatQRect(QDebug &debug, const Rect &rect) { - debug << rect.x() << ',' << rect.y() << ' ' << rect.width() << 'x' << rect.height(); + debug << rect.x() << ',' << rect.y() << ' '; + if constexpr (std::is_same_v) { + // QRect may overflow. Calculate width and height in higher precision. + const qint64 w = qint64(rect.right()) - rect.left() + 1; + const qint64 h = qint64(rect.bottom()) - rect.top() + 1; + debug << w << 'x' << h; + } else { + debug << rect.width() << 'x' << rect.height(); + } } template diff --git a/tests/auto/corelib/tools/qrect/tst_qrect.cpp b/tests/auto/corelib/tools/qrect/tst_qrect.cpp index c7c8b3a5601..ebf1d1b38bd 100644 --- a/tests/auto/corelib/tools/qrect/tst_qrect.cpp +++ b/tests/auto/corelib/tools/qrect/tst_qrect.cpp @@ -162,6 +162,8 @@ private slots: void smallRects() const; void toRect(); void span(); + + void debug(); }; // Used to work around some floating point precision problems. @@ -4499,5 +4501,33 @@ void tst_QRect::span() QCOMPARE(QRect::span(QPoint( 1, 10), QPoint(9, 0)), QRect(QPoint(1, 0), QPoint( 9, 10))); } +void tst_QRect::debug() +{ + QString str; + QDebug debug(&str); + + debug.nospace(); + + str.clear(); + debug << QRect(); + QCOMPARE(str, "QRect(0,0 0x0)"); + + str.clear(); + debug << QRect(10, 20, 30, 40); + QCOMPARE(str, "QRect(10,20 30x40)"); + + str.clear(); + debug << QRect(-10, -20, 30, 40); + QCOMPARE(str, "QRect(-10,-20 30x40)"); + + str.clear(); + debug << QRect(-10, -20, -30, -40); + QCOMPARE(str, "QRect(-10,-20 -30x-40)"); + + str.clear(); + debug << QRect(QPoint(INT_MIN, INT_MIN), QPoint(INT_MAX, INT_MAX)); + QCOMPARE(str, "QRect(-2147483648,-2147483648 4294967296x4294967296)"); +} + QTEST_MAIN(tst_QRect) #include "tst_qrect.moc"