summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Kelly <stephen.kelly@kdab.com>2012-10-18 13:36:02 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-10-22 19:36:43 +0200
commitefc475a996574364046335e2d66c4a091c5ccc31 (patch)
tree68df16afcf696b2972ac6099cc3dc9144826502e
parentd18eb260d70b75376411fe3f69da82bf46fb503f (diff)
Fix integer overflow in QSpinBox.
Change-Id: Ic204d42fbdffc44576f7e76132bc53621e836299 Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
-rw-r--r--src/widgets/widgets/qabstractspinbox.cpp19
-rw-r--r--tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp31
2 files changed, 48 insertions, 2 deletions
diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp
index f2914025f9..845cb5dbd0 100644
--- a/src/widgets/widgets/qabstractspinbox.cpp
+++ b/src/widgets/widgets/qabstractspinbox.cpp
@@ -1904,7 +1904,20 @@ QVariant operator+(const QVariant &arg1, const QVariant &arg2)
qWarning("QAbstractSpinBox: Internal error: Different types (%s vs %s) (%s:%d)",
arg1.typeName(), arg2.typeName(), __FILE__, __LINE__);
switch (arg1.type()) {
- case QVariant::Int: ret = QVariant(arg1.toInt() + arg2.toInt()); break;
+ case QVariant::Int: {
+ const int int1 = arg1.toInt();
+ const int int2 = arg2.toInt();
+ if (int1 > 0 && (int2 >= INT_MAX - int1)) {
+ // The increment overflows
+ ret = QVariant(INT_MAX);
+ } else if (int1 < 0 && (int2 <= INT_MIN - int1)) {
+ // The increment underflows
+ ret = QVariant(INT_MIN);
+ } else {
+ ret = QVariant(int1 + int2);
+ }
+ break;
+ }
case QVariant::Double: ret = QVariant(arg1.toDouble() + arg2.toDouble()); break;
case QVariant::DateTime: {
QDateTime a2 = arg2.toDateTime();
@@ -1962,7 +1975,9 @@ QVariant operator*(const QVariant &arg1, double multiplier)
QVariant ret;
switch (arg1.type()) {
- case QVariant::Int: ret = QVariant((int)(arg1.toInt() * multiplier)); break;
+ case QVariant::Int:
+ ret = static_cast<int>(qBound<double>(INT_MIN, arg1.toInt() * multiplier, INT_MAX));
+ break;
case QVariant::Double: ret = QVariant(arg1.toDouble() * multiplier); break;
case QVariant::DateTime: {
double days = QDATETIMEEDIT_DATE_MIN.daysTo(arg1.toDateTime().date()) * multiplier;
diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
index beea5f3052..6e1abb9fa9 100644
--- a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
+++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
@@ -135,6 +135,8 @@ private slots:
void sizeHint();
+ void integerOverflow();
+
void taskQTBUG_5008_textFromValueAndValidate();
public slots:
@@ -1014,6 +1016,35 @@ void tst_QSpinBox::taskQTBUG_5008_textFromValueAndValidate()
QCOMPARE(spinbox.text(), spinbox.locale().toString(spinbox.value()));
}
+void tst_QSpinBox::integerOverflow()
+{
+ QSpinBox sb;
+ sb.setRange(INT_MIN, INT_MAX);
+
+ sb.setValue(INT_MAX - 1);
+ sb.stepUp();
+ QCOMPARE(sb.value(), INT_MAX);
+ sb.stepUp();
+ QCOMPARE(sb.value(), INT_MAX);
+
+ sb.setValue(INT_MIN + 1);
+ sb.stepDown();
+ QCOMPARE(sb.value(), INT_MIN);
+ sb.stepDown();
+ QCOMPARE(sb.value(), INT_MIN);
+
+ sb.setValue(0);
+ QCOMPARE(sb.value(), 0);
+ sb.setSingleStep(INT_MAX);
+ sb.stepUp();
+ QCOMPARE(sb.value(), INT_MAX);
+ sb.stepDown();
+ QCOMPARE(sb.value(), 0);
+ sb.stepDown();
+ QCOMPARE(sb.value(), INT_MIN + 1);
+ sb.stepDown();
+ QCOMPARE(sb.value(), INT_MIN);
+}
QTEST_MAIN(tst_QSpinBox)
#include "tst_qspinbox.moc"