From 7a8baa2583d8a1dea01c82bb00ab78bb27390776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20L=C3=B6hning?= Date: Mon, 31 Mar 2025 23:13:05 +0200 Subject: [PATCH] Return early if qt_mapFillRect will return empty QRect Credit to OSS-Fuzz, this fixes issue 406541912. When rendering the svg image from that report, an integer overflow happend while calculating a QRect which is empty anyway. To avoid that, return an empty, default constructed QRect instead of calculating further. Picking back to 6.5 which is the oldest maintained version which contains this function. Pick-to: 6.8 6.5 Change-Id: I1a0d1310c55f7be613a6292f36481ac7c7e5b56f Reviewed-by: Eirik Aavitsland (cherry picked from commit d1b88f8b73c16e1ee362fa4cc853bcaadae0df6a) Reviewed-by: Qt Cherry-pick Bot --- src/gui/painting/qmath_p.h | 4 ++++ .../gui/painting/qpainter/tst_qpainter.cpp | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/gui/painting/qmath_p.h b/src/gui/painting/qmath_p.h index d4e5be8339b..d4a74af5c56 100644 --- a/src/gui/painting/qmath_p.h +++ b/src/gui/painting/qmath_p.h @@ -34,6 +34,10 @@ inline QRect qt_mapFillRect(const QRectF &rect, const QTransform &xf) // as that can sometimes be slightly off around the .5 point, leading to wrong rounding QPoint pt1 = xf.map(rect.topLeft()).toPoint(); QPoint pt2 = xf.map(rect.bottomRight()).toPoint(); + // cut short if the result will be an empty QRect anyway + // side effect: avoids overflows in the calculations below + if (Q_UNLIKELY(pt1.x() == pt2.x() || pt1.y() == pt2.y())) + return QRect(); // Normalize and adjust for the QRect vs. QRectF bottomright return QRect::span(pt1, pt2).adjusted(0, 0, -1, -1); } diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index 9ef5c6f34e1..575b4bb70a0 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -1741,6 +1741,25 @@ void tst_QPainter::setClipRect() p.setClipRect(QRectF(10.5, 10.5, 10.5, -10.5)); QVERIFY(p.clipRegion().isEmpty()); } + + // extreme transform, values reverse-engineered from oss-fuzz issue 406541912 + // crashed with a failed assert due to an integer overflow + { + QPainter p(&img); + p.setTransform(QTransform(37.7, 0., 0., + 0., 233., 0., + 18.85, -163099999883.5, 1.)); + p.setClipRect(QRect(0, 0, 10, 1), Qt::ReplaceClip); + } + + // the same extreme transform, edited to overflow on the x-axis instead + { + QPainter p(&img); + p.setTransform(QTransform(233., 0., 0., + 0., 37.7, 0., + -163099999883.5, 18.85, 1.)); + p.setClipRect(QRect(0, 0, 1, 10), Qt::ReplaceClip); + } } /*