Fix crash issue for path animation and path interpulator
authorCharles Yin <charles.yin@nokia.com>
Thu, 22 Mar 2012 04:07:28 +0000 (14:07 +1000)
committerQt by Nokia <qt-info@nokia.com>
Fri, 23 Mar 2012 04:19:35 +0000 (05:19 +0100)
When set progress value out of [0,1], path animation and
path interpulator should make sure the value be modified
in the valid value range, otherwise the QQuickPath::backwardsPointAt()
will crash.

Task-number: QTBUG-24308
Change-Id: Icd6e9165c9f844ddb8ec84c229eac4db5246a749
Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
src/quick/items/qquickitemanimation.cpp
src/quick/util/qquickpath.cpp
src/quick/util/qquickpathinterpolator.cpp
tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml [new file with mode: 0644]
tests/auto/quick/qquickanimations/tst_qquickanimations.cpp

index a1c398e..3e84eb6 100644 (file)
@@ -927,6 +927,8 @@ QAbstractAnimationJob* QQuickPathAnimation::transition(QQuickStateActions &actio
 
 void QQuickPathAnimationUpdater::setValue(qreal v)
 {
+    v = qMin(qMax(v, (qreal)0.0), (qreal)1.0);;
+
     if (interruptStart.isValid()) {
         if (reverse)
             v = 1 - v;
index adf4242..8dadab6 100644 (file)
@@ -527,6 +527,8 @@ QPointF QQuickPath::sequentialPointAt(qreal p, qreal *angle) const
 
 QPointF QQuickPath::sequentialPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QQuickCachedBezier &prevBez, qreal p, qreal *angle)
 {
+    Q_ASSERT(p >= 0.0 && p <= 1.0);
+
     if (!prevBez.isValid)
         return p > .5 ? backwardsPointAt(path, pathLength, attributePoints, prevBez, p, angle) :
                         forwardsPointAt(path, pathLength, attributePoints, prevBez, p, angle);
index 2b5fb62..ee1424b 100644 (file)
@@ -102,6 +102,8 @@ qreal QQuickPathInterpolator::progress() const
 
 void QQuickPathInterpolator::setProgress(qreal progress)
 {
+    progress = qMin(qMax(progress, (qreal)0.0), (qreal)1.0);
+
     if (progress == _progress)
         return;
     _progress = progress;
diff --git a/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml b/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml
new file mode 100644 (file)
index 0000000..1ee76f6
--- /dev/null
@@ -0,0 +1,26 @@
+import QtQuick 2.0
+Item {
+    id: root
+    width: 450; height: 600
+
+    Rectangle {
+        objectName:"rect"
+        id: rect
+        x:200
+        y:500
+        width: 225; height: 40
+        color: "lightsteelblue"
+    }
+    PathAnimation {
+        id:anim
+        running:true
+        duration: 200
+
+        easing.type: Easing.InOutBack
+
+        target:rect
+        path: Path {
+            PathLine { x: 0; y: 0 }
+        }
+    }
+}
\ No newline at end of file
index d71100d..166f4b8 100644 (file)
@@ -107,6 +107,7 @@ private slots:
     void pauseBug();
     void loopingBug();
     void anchorBug();
+    void pathAnimationInOutBackBug();
 };
 
 #define QTIMED_COMPARE(lhs, rhs) do { \
@@ -455,6 +456,13 @@ void tst_qquickanimations::pathInterpolator()
     QCOMPARE(interpolator->x(), qreal(300));
     QCOMPARE(interpolator->y(), qreal(300));
     QCOMPARE(interpolator->angle(), qreal(0));
+
+    //for path interpulator the progress value must be [0,1] range.
+    interpolator->setProgress(1.1);
+    QCOMPARE(interpolator->progress(), qreal(1));
+
+    interpolator->setProgress(-0.000123);
+    QCOMPARE(interpolator->progress(), qreal(0));
 }
 
 void tst_qquickanimations::pathInterpolatorBackwardJump()
@@ -1171,6 +1179,22 @@ void tst_qquickanimations::runningTrueBug()
     QVERIFY(cloud->x() > qreal(0));
 }
 
+//QTBUG-24308
+void tst_qquickanimations::pathAnimationInOutBackBug()
+{
+    //ensure we don't pass bad progress value (out of [0,1]) to  QQuickPath::backwardsPointAt()
+    QQmlEngine engine;
+    QQmlComponent c(&engine, testFileUrl("pathAnimationInOutBackCrash.qml"));
+    QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+    QVERIFY(item);
+
+    QQuickRectangle *rect = item->findChild<QQuickRectangle *>("rect");
+    QVERIFY(rect);
+    QTest::qWait(1000);
+    QCOMPARE(rect->x(), qreal(0));
+    QCOMPARE(rect->y(), qreal(0));
+}
+
 //QTBUG-12805
 void tst_qquickanimations::nonTransitionBug()
 {