diff options
author | Stephen Kelly <stephen.kelly@kdab.com> | 2012-10-18 13:36:02 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-10-22 19:36:43 +0200 |
commit | efc475a996574364046335e2d66c4a091c5ccc31 (patch) | |
tree | 68df16afcf696b2972ac6099cc3dc9144826502e | |
parent | d18eb260d70b75376411fe3f69da82bf46fb503f (diff) |
Fix integer overflow in QSpinBox.
Change-Id: Ic204d42fbdffc44576f7e76132bc53621e836299
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
-rw-r--r-- | src/widgets/widgets/qabstractspinbox.cpp | 19 | ||||
-rw-r--r-- | tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp | 31 |
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" |