QRadialGradient: Fix undefined behavior
The UBSan raises a division by zero in getRadialGradientValues. This can be avoided by calculating the inverse in qt_fetch_radial_gradient_template as a checker is done to avoid division by zero there. (Credit to OSS-Fuzz) Fixes: QTBUG-120332 Change-Id: I798d1efc87ee07df7ca6f401aa476013cdbffe42 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io> (cherry picked from commit 69bed6cd3f12a3c1b0182c5a3706efa617090cfa) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
b814f73fb6
commit
4596aa7bfe
@ -3413,7 +3413,6 @@ static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const Q
|
||||
v->sqrfr = data->gradient.radial.focal.radius * data->gradient.radial.focal.radius;
|
||||
|
||||
v->a = v->dr * v->dr - v->dx*v->dx - v->dy*v->dy;
|
||||
v->inv2a = 1 / (2 * v->a);
|
||||
|
||||
v->extended = !qFuzzyIsNull(data->gradient.radial.focal.radius) || v->a <= 0;
|
||||
}
|
||||
|
@ -174,7 +174,6 @@ struct RadialGradientValues
|
||||
qreal dr;
|
||||
qreal sqrfr;
|
||||
qreal a;
|
||||
qreal inv2a;
|
||||
bool extended;
|
||||
};
|
||||
|
||||
@ -402,12 +401,12 @@ const BlendType * QT_FASTCALL qt_fetch_radial_gradient_template(BlendType *buffe
|
||||
bool affine = !data->m13 && !data->m23;
|
||||
|
||||
BlendType *end = buffer + length;
|
||||
qreal inv_a = 1 / qreal(2 * op->radial.a);
|
||||
|
||||
if (affine) {
|
||||
rx -= data->gradient.radial.focal.x;
|
||||
ry -= data->gradient.radial.focal.y;
|
||||
|
||||
qreal inv_a = 1 / qreal(2 * op->radial.a);
|
||||
|
||||
const qreal delta_rx = data->m11;
|
||||
const qreal delta_ry = data->m12;
|
||||
|
||||
@ -452,8 +451,8 @@ const BlendType * QT_FASTCALL qt_fetch_radial_gradient_template(BlendType *buffe
|
||||
if (det >= 0) {
|
||||
qreal detSqrt = qSqrt(det);
|
||||
|
||||
qreal s0 = (-b - detSqrt) * op->radial.inv2a;
|
||||
qreal s1 = (-b + detSqrt) * op->radial.inv2a;
|
||||
qreal s0 = (-b - detSqrt) * inv_a;
|
||||
qreal s1 = (-b + detSqrt) * inv_a;
|
||||
|
||||
qreal s = qMax(s0, s1);
|
||||
|
||||
|
@ -169,6 +169,7 @@ private slots:
|
||||
void radialGradientRgb30();
|
||||
#endif
|
||||
|
||||
void radialGradient_QTBUG120332_ubsan();
|
||||
void fpe_pixmapTransform();
|
||||
void fpe_zeroLengthLines();
|
||||
void fpe_divByZero();
|
||||
@ -3896,6 +3897,21 @@ void tst_QPainter::gradientPixelFormat()
|
||||
QCOMPARE(a, b.convertToFormat(QImage::Format_ARGB32_Premultiplied));
|
||||
}
|
||||
|
||||
void tst_QPainter::radialGradient_QTBUG120332_ubsan()
|
||||
{
|
||||
// Check if Radial Gradient will cause division by zero or not when
|
||||
// the center point coincide with the focal point.
|
||||
QImage image(8, 8, QImage::Format_ARGB32_Premultiplied);
|
||||
QPainter painter(&image);
|
||||
|
||||
QPointF center(0.5, 0.5);
|
||||
QPointF focal(0.5, 0.5);
|
||||
QRadialGradient gradient(center, 0.5, focal, 0.5);
|
||||
gradient.setColorAt(0, Qt::blue);
|
||||
gradient.setColorAt(1, Qt::red);
|
||||
painter.fillRect(image.rect(), QBrush(gradient));
|
||||
}
|
||||
|
||||
void tst_QPainter::gradientInterpolation()
|
||||
{
|
||||
QImage image(256, 8, QImage::Format_ARGB32_Premultiplied);
|
||||
|
Loading…
x
Reference in New Issue
Block a user