diff options
author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com> | 2009-09-17 08:21:49 (GMT) |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com> | 2009-09-17 08:25:37 (GMT) |
commit | 603c423fc2ee2b9393e3c288e76354de0e0c1cc7 (patch) | |
tree | 1c8168c14f9443a7e9c8dced5f0e0737d9b4482e | |
parent | 9cef27f506e15681f9935a1c00c9df3c6271d5f2 (diff) | |
download | Qt-603c423fc2ee2b9393e3c288e76354de0e0c1cc7.zip Qt-603c423fc2ee2b9393e3c288e76354de0e0c1cc7.tar.gz Qt-603c423fc2ee2b9393e3c288e76354de0e0c1cc7.tar.bz2 |
Fix crash or painting error when drawing dashed lines with penWidth > 1
Since the width is multiplied into the dash, it needs to be divided out,
otherwise you can get a dashOffset which is greater than the pattern at
the index, and the dash can become negative. This will in turn lead to
passing a negative width to the rasterizer, which at some point will
get cast to an unsigned int and overflow. Depending on the position of
the line and size of the buffer, this will either crash or produce
garbled output.
Task-number: QT-4444
Reviewed-by: Samuel
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 2 | ||||
-rw-r--r-- | src/gui/painting/qrasterizer.cpp | 4 | ||||
-rw-r--r-- | tests/auto/qpainter/tst_qpainter.cpp | 25 |
3 files changed, 29 insertions, 2 deletions
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index bd12fdb..bcea1ec 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -3564,7 +3564,7 @@ void QRasterPaintEnginePrivate::rasterizeLine_dashed(QLineF line, if (dash >= length) { dash = length; - *dashOffset += dash; + *dashOffset += dash / width; length = 0; } else { *dashOffset = 0; diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp index 4500756..2b6791d 100644 --- a/src/gui/painting/qrasterizer.cpp +++ b/src/gui/painting/qrasterizer.cpp @@ -706,10 +706,12 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, if (a == b || width == 0 || d->clipRect.isEmpty()) return; + Q_ASSERT(width > 0.0); + QPointF pa = a; QPointF pb = b; - QPointF offs = QPointF(qAbs(b.y() - a.y()), qAbs(b.x() - a.x())) * width * 0.5; + QPointF offs = QPointF(qAbs(b.y() - a.y()), qAbs(b.x() - a.x())) * width * 0.5; if (squareCap) offs += QPointF(offs.y(), offs.x()); const QRectF clip(d->clipRect.topLeft() - offs, d->clipRect.bottomRight() + QPoint(1, 1) + offs); diff --git a/tests/auto/qpainter/tst_qpainter.cpp b/tests/auto/qpainter/tst_qpainter.cpp index e434ed6..c0eac21 100644 --- a/tests/auto/qpainter/tst_qpainter.cpp +++ b/tests/auto/qpainter/tst_qpainter.cpp @@ -230,6 +230,8 @@ private slots: void zeroOpacity(); void emptyClip(); + void taskQT4444_dontOverflowDashOffset(); + private: void fillData(); QColor baseColor( int k, int intensity=255 ); @@ -4239,5 +4241,28 @@ void tst_QPainter::emptyClip() p.fillPath(path, Qt::green); } +void tst_QPainter::taskQT4444_dontOverflowDashOffset() +{ + QPainter p; + + QPen pen; + pen.setWidth(2); + pen.setStyle(Qt::DashDotLine); + + QPointF point[4]; + point[0] = QPointF(182.50868749707968,347.78457234212630); + point[1] = QPointF(182.50868749707968,107.22501998401277); + point[2] = QPointF(182.50868749707968,107.22501998401277); + point[3] = QPointF(520.46600762283651,107.22501998401277); + + QImage crashImage(QSize(1000, 120), QImage::Format_ARGB32_Premultiplied); + p.begin(&crashImage); + p.setPen(pen); + p.drawLines(point, 2); + p.end(); + + QVERIFY(true); // Don't crash +} + QTEST_MAIN(tst_QPainter) #include "tst_qpainter.moc" |