Fix UB (signed integer overflows) in QProgressBar

The expression 'minimum - 1' invokes UB when 'minimum == INT_MIN'.
Likewise, the expression 'maximum - minimum' invokes UB when
'qint64(maximum) - minimum > INT_MAX'.

Fix by restructuring the code or else by using 64-bit arithmetic.

Change-Id: I352eafa72f28ae907f41c8f88abcf0a81705c718
Task-number: QTBUG-57857
Reviewed-by: David Faure <david.faure@kdab.com>
bb10
Marc Mutz 2017-01-04 13:43:44 +01:00
parent fb85a72325
commit f4d3c87f0c
1 changed files with 8 additions and 6 deletions

View File

@ -144,16 +144,17 @@ bool QProgressBarPrivate::repaintRequired() const
if (value == lastPaintedValue)
return false;
int valueDifference = qAbs(value - lastPaintedValue);
const auto valueDifference = qAbs(qint64(value) - lastPaintedValue);
// Check if the text needs to be repainted
if (value == minimum || value == maximum)
return true;
const auto totalSteps = qint64(maximum) - minimum;
if (textVisible) {
if ((format.contains(QLatin1String("%v"))))
return true;
if ((format.contains(QLatin1String("%p"))
&& valueDifference >= qAbs((maximum - minimum) / 100)))
&& valueDifference >= qAbs(totalSteps / 100)))
return true;
}
@ -166,7 +167,7 @@ bool QProgressBarPrivate::repaintRequired() const
// (valueDifference / (maximum - minimum) > cw / groove.width())
// transformed to avoid integer division.
int grooveBlock = (q->orientation() == Qt::Horizontal) ? groove.width() : groove.height();
return (valueDifference * grooveBlock > cw * (maximum - minimum));
return valueDifference * grooveBlock > cw * totalSteps;
}
/*!
@ -260,9 +261,10 @@ QProgressBar::~QProgressBar()
void QProgressBar::reset()
{
Q_D(QProgressBar);
d->value = d->minimum - 1;
if (d->minimum == INT_MIN)
d->value = INT_MIN;
else
d->value = d->minimum - 1;
repaint();
}
@ -358,7 +360,7 @@ void QProgressBar::setRange(int minimum, int maximum)
d->minimum = minimum;
d->maximum = qMax(minimum, maximum);
if (d->value < (d->minimum - 1) || d->value > d->maximum)
if (d->value < qint64(d->minimum) - 1 || d->value > d->maximum)
reset();
else
update();