From 45bd1e737f2f76bbc9943995734c6ecb0a23935b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Samuel=20R=C3=B8dal?= <samuel.rodal@nokia.com>
Date: Mon, 28 Mar 2011 12:43:05 +0200
Subject: Fixed infinite loop in QPainterPath::intersects() when qreal=float.

Similar to c30714122c58a3dc6fd8401427da60c4afc4127b, we need to limit
the max number of recursions.

Task-number: QTBUG-16422
Reviewed-by: Kim
---
 src/gui/painting/qpainterpath.cpp            | 16 ++++++++--------
 tests/auto/qpainterpath/tst_qpainterpath.cpp |  4 ++++
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 0948a64..0bb2901 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -1863,39 +1863,39 @@ static bool qt_painterpath_isect_line_rect(qreal x1, qreal y1, qreal x2, qreal y
     return false;
 }
 
-static bool qt_isect_curve_horizontal(const QBezier &bezier, qreal y, qreal x1, qreal x2)
+static bool qt_isect_curve_horizontal(const QBezier &bezier, qreal y, qreal x1, qreal x2, int depth = 0)
 {
     QRectF bounds = bezier.bounds();
 
     if (y >= bounds.top() && y < bounds.bottom()
         && bounds.right() >= x1 && bounds.left() < x2) {
         const qreal lower_bound = qreal(.01);
-        if (bounds.width() < lower_bound && bounds.height() < lower_bound)
+        if (depth == 32 || bounds.width() < lower_bound && bounds.height() < lower_bound)
             return true;
 
         QBezier first_half, second_half;
         bezier.split(&first_half, &second_half);
-        if (qt_isect_curve_horizontal(first_half, y, x1, x2)
-            || qt_isect_curve_horizontal(second_half, y, x1, x2))
+        if (qt_isect_curve_horizontal(first_half, y, x1, x2, depth + 1)
+            || qt_isect_curve_horizontal(second_half, y, x1, x2, depth + 1))
             return true;
     }
     return false;
 }
 
-static bool qt_isect_curve_vertical(const QBezier &bezier, qreal x, qreal y1, qreal y2)
+static bool qt_isect_curve_vertical(const QBezier &bezier, qreal x, qreal y1, qreal y2, int depth = 0)
 {
     QRectF bounds = bezier.bounds();
 
     if (x >= bounds.left() && x < bounds.right()
         && bounds.bottom() >= y1 && bounds.top() < y2) {
         const qreal lower_bound = qreal(.01);
-        if (bounds.width() < lower_bound && bounds.height() < lower_bound)
+        if (depth == 32 || bounds.width() < lower_bound && bounds.height() < lower_bound)
             return true;
 
         QBezier first_half, second_half;
         bezier.split(&first_half, &second_half);
-        if (qt_isect_curve_vertical(first_half, x, y1, y2)
-            || qt_isect_curve_vertical(second_half, x, y1, y2))
+        if (qt_isect_curve_vertical(first_half, x, y1, y2, depth + 1)
+            || qt_isect_curve_vertical(second_half, x, y1, y2, depth + 1))
             return true;
     }
      return false;
diff --git a/tests/auto/qpainterpath/tst_qpainterpath.cpp b/tests/auto/qpainterpath/tst_qpainterpath.cpp
index 4ade9ad..bc3b5d9 100644
--- a/tests/auto/qpainterpath/tst_qpainterpath.cpp
+++ b/tests/auto/qpainterpath/tst_qpainterpath.cpp
@@ -411,6 +411,10 @@ void tst_QPainterPath::intersects_QRectF_data()
 
     QTest::newRow("horizontal line") << linePath(0, 0, 10, 0) << QRectF(1, -1, 2, 2) << true;
     QTest::newRow("vertical line") << linePath(0, 0, 0, 10) << QRectF(-1, 1, 2, 2) << true;
+
+    path = QPainterPath();
+    path.addEllipse(QRectF(-5000.0, -5000.0, 1500000.0, 1500000.0));
+    QTest::newRow("huge ellipse, qreal=float crash") << path << QRectF(1100000.35, 1098000.2, 1500000.0, 1500000.0) << true;
 }
 
 void tst_QPainterPath::intersects_QRectF()
-- 
cgit v0.12