diff options
author | Robert Löhning <robert.loehning@qt.io> | 2022-03-04 12:16:06 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-03-10 12:42:35 +0000 |
commit | 7c88d9c18eae029d92ba54b23e6ae94b8f77af07 (patch) | |
tree | 4473ee6bddb7b8479ca01f67fea6f1ad27ea1e87 | |
parent | 47a2a235311df1546a440e4efb932a5cf56a63eb (diff) |
QStyle: Fix overflows and crash when converting slider positions
Qt Creator crashes when max is INT_MAX and min is -1, see bugreport.
Change-Id: I441e76c0ff87052083ed3d77e6085b186402e5d8
Fixes: QTBUG-101581
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 4b49c2006f3a0e957d0c5d8c09f32c4ea321885a)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/widgets/styles/qstyle.cpp | 14 | ||||
-rw-r--r-- | tests/auto/widgets/styles/qstyle/tst_qstyle.cpp | 105 |
2 files changed, 112 insertions, 7 deletions
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 9301141c07..827f51a7d9 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -2262,8 +2262,8 @@ int QStyle::sliderPositionFromValue(int min, int max, int logicalValue, int span if (logicalValue > max) return upsideDown ? span : min; - uint range = max - min; - uint p = upsideDown ? max - logicalValue : logicalValue - min; + const uint range = qint64(max) - min; + const uint p = upsideDown ? qint64(max) - logicalValue : qint64(logicalValue) - min; if (range > (uint)INT_MAX/4096) { double dpos = (double(p))/(double(range)/span); @@ -2305,15 +2305,15 @@ int QStyle::sliderValueFromPosition(int min, int max, int pos, int span, bool up if (pos >= span) return upsideDown ? min : max; - uint range = max - min; + const qint64 range = qint64(max) - min; if ((uint)span > range) { - int tmp = (2 * pos * range + span) / (2 * span); + const int tmp = (2 * range * pos + span) / (qint64(2) * span); return upsideDown ? max - tmp : tmp + min; } else { - uint div = range / span; - uint mod = range % span; - int tmp = pos * div + (2 * pos * mod + span) / (2 * span); + const qint64 div = range / span; + const qint64 mod = range % span; + const int tmp = pos * div + (2 * mod * pos + span) / (qint64(2) * span); return upsideDown ? max - tmp : tmp + min; } // equiv. to min + (pos*range)/span + 0.5 diff --git a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp index 0578d5ce70..943fc89f1c 100644 --- a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp +++ b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp @@ -92,6 +92,11 @@ private slots: void testProxyCalled(); void testStyleOptionInit(); + + void sliderPositionFromValue_data(); + void sliderPositionFromValue(); + void sliderValueFromPosition_data(); + void sliderValueFromPosition(); private: bool testAllFunctions(QStyle *); bool testScrollBarSubControls(const QStyle *style); @@ -662,5 +667,105 @@ void tst_QStyle::testStyleOptionInit() } } +void tst_QStyle::sliderPositionFromValue_data() +{ + QTest::addColumn<int>("min"); + QTest::addColumn<int>("max"); + QTest::addColumn<int>("value"); + QTest::addColumn<int>("span"); + QTest::addColumn<bool>("upsideDown"); + QTest::addColumn<int>("position"); + + QTest::addRow("no span") << 12 << 56 << 34 << 0 << false << 0; + QTest::addRow("no span inverse") << 12 << 56 << 34 << 0 << true << 0; + + QTest::addRow("value too small") << 34 << 56 << 12 << 2000 << false << 0; + + QTest::addRow("no-range") << 12 << 12 << 12 << 2000 << false << 0; + QTest::addRow("no-range-inverse") << 12 << 12 << 12 << 2000 << true << 0; + + QTest::addRow("close-to-max") << 12 << 34 << 33 << 2000 << false << 1909; + QTest::addRow("at-max") << 12 << 34 << 34 << 2000 << false << 2000; + QTest::addRow("close-to-max-inverse") << 12 << 34 << 33 << 2000 << true << 91; + QTest::addRow("at-max-inverse") << 12 << 34 << 34 << 2000 << true << 0; + + QTest::addRow("big-range") << 100000 << 700000 << 250000 << 2000 << false << 500; + QTest::addRow("big-range-inverse") << 100000 << 700000 << 250000 << 2000 << true << 1500; + + QTest::addRow("across-zero") << -1000 << 1000 << -500 << 100 << false << 25; + QTest::addRow("across-zero-inverse") << -1000 << 1000 << -500 << 100 << true << 75; + + QTest::addRow("span>range") << 0 << 100 << 60 << 2000 << false << 1200; + QTest::addRow("span>range-inverse") << 0 << 100 << 60 << 2000 << true << 800; + + QTest::addRow("overflow1 (QTBUG-101581)") << -1 << INT_MAX << 235 << 891 << false << 0; + QTest::addRow("overflow2") << INT_MIN << INT_MAX << 10 << 100 << false << 50; + QTest::addRow("overflow2-inverse") << INT_MIN << INT_MAX << 10 << 100 << true << 49; + QTest::addRow("overflow3") << INT_MIN << INT_MAX << -10 << 100 << false << 49; + QTest::addRow("overflow3-inverse") << INT_MIN << INT_MAX << -10 << 100 << true << 50; +} + +void tst_QStyle::sliderPositionFromValue() +{ + QFETCH(int, min); + QFETCH(int, max); + QFETCH(int, value); + QFETCH(int, span); + QFETCH(bool, upsideDown); + QFETCH(int, position); + + QCOMPARE(QStyle::sliderPositionFromValue(min, max, value, span, upsideDown), position); +} + +void tst_QStyle::sliderValueFromPosition_data() +{ + QTest::addColumn<int>("min"); + QTest::addColumn<int>("max"); + QTest::addColumn<int>("position"); + QTest::addColumn<int>("span"); + QTest::addColumn<bool>("upsideDown"); + QTest::addColumn<int>("value"); + + QTest::addRow("position zero") << 0 << 100 << 0 << 2000 << false << 0; + QTest::addRow("position zero inverse") << 0 << 100 << 0 << 2000 << true << 100; + + QTest::addRow("span zero") << 0 << 100 << 1200 << 0 << false << 0; + QTest::addRow("span zero inverse") << 0 << 100 << 1200 << 0 << true << 100; + + QTest::addRow("position > span") << -300 << -200 << 2 << 1 << false << -200; + QTest::addRow("position > span inverse") << -300 << -200 << 2 << 1 << true << -300; + + QTest::addRow("large") << 0 << 100 << 1200 << 2000 << false << 60; + QTest::addRow("large-inverse") << 0 << 100 << 1200 << 2000 << true << 40; + + QTest::addRow("normal") << 0 << 100 << 12 << 20 << false << 60; + QTest::addRow("inverse") << 0 << 100 << 12 << 20 << true << 40; + + QTest::addRow("overflow1") << -1 << INT_MAX << 10 << 10 << false << INT_MAX; + QTest::addRow("overflow1-inverse") << -1 << INT_MAX << 10 << 10 << true << -1; + QTest::addRow("overflow2") << INT_MIN << INT_MAX << 5 << 10 << false << 0; + QTest::addRow("overflow2-inverse") << INT_MIN << INT_MAX << 5 << 10 << true << -1; + QTest::addRow("overflow3") << INT_MIN << 0 << 0 << 10 << false << INT_MIN; + QTest::addRow("overflow3-inverse") << INT_MIN << 0 << 0 << 10 << true << 0; + + QTest::addRow("overflow4") << 0 << INT_MAX << INT_MAX/2-6 << INT_MAX/2-5 << false << INT_MAX-2; + QTest::addRow("overflow4-inverse") << 0 << INT_MAX << INT_MAX/2-6 << INT_MAX/2-5 << true << 2; + + QTest::addRow("overflow5") << 0 << 4 << INT_MAX/4 << INT_MAX << false << 1; + QTest::addRow("overflow5-inverse") << 0 << 4 << INT_MAX/4 << INT_MAX << true << 3; +} + +void tst_QStyle::sliderValueFromPosition() +{ + QFETCH(int, min); + QFETCH(int, max); + QFETCH(int, position); + QFETCH(int, span); + QFETCH(bool, upsideDown); + QFETCH(int, value); + + QCOMPARE(QStyle::sliderValueFromPosition(min, max, position, span, upsideDown), value); +} + QTEST_MAIN(tst_QStyle) #include "tst_qstyle.moc" |