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 Pick-to: 6.2 6.3 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
a6a480ddcb
commit
4b49c2006f
@ -2262,8 +2262,8 @@ int QStyle::sliderPositionFromValue(int min, int max, int logicalValue, int span
|
|||||||
if (logicalValue > max)
|
if (logicalValue > max)
|
||||||
return upsideDown ? span : min;
|
return upsideDown ? span : min;
|
||||||
|
|
||||||
uint range = max - min;
|
const uint range = qint64(max) - min;
|
||||||
uint p = upsideDown ? max - logicalValue : logicalValue - min;
|
const uint p = upsideDown ? qint64(max) - logicalValue : qint64(logicalValue) - min;
|
||||||
|
|
||||||
if (range > (uint)INT_MAX/4096) {
|
if (range > (uint)INT_MAX/4096) {
|
||||||
double dpos = (double(p))/(double(range)/span);
|
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)
|
if (pos >= span)
|
||||||
return upsideDown ? min : max;
|
return upsideDown ? min : max;
|
||||||
|
|
||||||
uint range = max - min;
|
const qint64 range = qint64(max) - min;
|
||||||
|
|
||||||
if ((uint)span > range) {
|
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;
|
return upsideDown ? max - tmp : tmp + min;
|
||||||
} else {
|
} else {
|
||||||
uint div = range / span;
|
const qint64 div = range / span;
|
||||||
uint mod = range % span;
|
const qint64 mod = range % span;
|
||||||
int tmp = pos * div + (2 * pos * mod + span) / (2 * span);
|
const int tmp = pos * div + (2 * mod * pos + span) / (qint64(2) * span);
|
||||||
return upsideDown ? max - tmp : tmp + min;
|
return upsideDown ? max - tmp : tmp + min;
|
||||||
}
|
}
|
||||||
// equiv. to min + (pos*range)/span + 0.5
|
// equiv. to min + (pos*range)/span + 0.5
|
||||||
|
@ -92,6 +92,11 @@ private slots:
|
|||||||
|
|
||||||
void testProxyCalled();
|
void testProxyCalled();
|
||||||
void testStyleOptionInit();
|
void testStyleOptionInit();
|
||||||
|
|
||||||
|
void sliderPositionFromValue_data();
|
||||||
|
void sliderPositionFromValue();
|
||||||
|
void sliderValueFromPosition_data();
|
||||||
|
void sliderValueFromPosition();
|
||||||
private:
|
private:
|
||||||
bool testAllFunctions(QStyle *);
|
bool testAllFunctions(QStyle *);
|
||||||
bool testScrollBarSubControls(const QStyle *style);
|
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)
|
QTEST_MAIN(tst_QStyle)
|
||||||
#include "tst_qstyle.moc"
|
#include "tst_qstyle.moc"
|
||||||
|
Loading…
Reference in New Issue
Block a user