_q_interpolate<T> is unsafe with unsigned template arguments

_q_interpolate<T> subtracts 2 arguments of type T,
for unsigned types this can cause wrapping around

Task-number: QTBUG-57925
Change-Id: Iffa59f413579a3d5de8cb728fe71443d8e8a04aa
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
bb10
Luca Beldi 2018-08-22 08:21:01 +01:00
parent 76c328b2b3
commit 02b3d43fd4
2 changed files with 38 additions and 1 deletions

View File

@ -58,6 +58,8 @@
#include "private/qabstractanimation_p.h"
#include <type_traits>
#ifndef QT_NO_ANIMATION
QT_BEGIN_NAMESPACE
@ -104,7 +106,17 @@ public:
};
//this should make the interpolation faster
template<typename T> inline T _q_interpolate(const T &f, const T &t, qreal progress)
template<typename T>
typename std::enable_if<std::is_unsigned<T>::value, T>::type
_q_interpolate(const T &f, const T &t, qreal progress)
{
return T(f + t * progress - f * progress);
}
// the below will apply also to all non-arithmetic types
template<typename T>
typename std::enable_if<!std::is_unsigned<T>::value, T>::type
_q_interpolate(const T &f, const T &t, qreal progress)
{
return T(f + (t - f) * progress);
}

View File

@ -43,6 +43,7 @@ private slots:
void keyValueAt();
void keyValues();
void duration();
void interpolation();
};
class TestableQVariantAnimation : public QVariantAnimation
@ -129,6 +130,30 @@ void tst_QVariantAnimation::duration()
QCOMPARE(anim.duration(), 500);
}
void tst_QVariantAnimation::interpolation()
{
QVariantAnimation unsignedAnim;
unsignedAnim.setStartValue(100u);
unsignedAnim.setEndValue(0u);
unsignedAnim.setDuration(100);
unsignedAnim.setCurrentTime(50);
QCOMPARE(unsignedAnim.currentValue().toUInt(), 50u);
QVariantAnimation signedAnim;
signedAnim.setStartValue(100);
signedAnim.setEndValue(0);
signedAnim.setDuration(100);
signedAnim.setCurrentTime(50);
QCOMPARE(signedAnim.currentValue().toInt(), 50);
QVariantAnimation pointAnim;
pointAnim.setStartValue(QPoint(100, 100));
pointAnim.setEndValue(QPoint(0, 0));
pointAnim.setDuration(100);
pointAnim.setCurrentTime(50);
QCOMPARE(pointAnim.currentValue().toPoint(), QPoint(50, 50));
}
QTEST_MAIN(tst_QVariantAnimation)
#include "tst_qvariantanimation.moc"