QImage: introduce a class invariant that format() is in-range
Coverity complains that image.format() is used to index into qPixelLayouts[] when it may be NImageFormats. Most code paths (e.g. QImageData::create()) defended against that, but e.g. QImage::reinterpretAsFormat() did not (at least not overtly), as didn't some of the backend functions. Add checks, document the invariant on 'format' and assert it in QImage::format(). If this doesn't convince Coverity, we'll need to turn qPixelLayouts[] into a function, so that it can defend itself against out-of-bounds access. Pick-to: 6.9 6.8 Coverity-Id: 390711 Coverity-Id: 390720 Coverity-Id: 390758 Change-Id: I29431193face3cae8be56f01da8dced19c3abb38 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
This commit is contained in:
parent
1593220552
commit
a2e60ebee3
@ -2158,6 +2158,11 @@ void QImage::setColorCount(int colorCount)
|
||||
*/
|
||||
QImage::Format QImage::format() const
|
||||
{
|
||||
if (d) {
|
||||
// Class Invariant Check
|
||||
Q_ASSERT(d->format < NImageFormats);
|
||||
Q_ASSERT(d->format > Format_Invalid);
|
||||
}
|
||||
return d ? d->format : Format_Invalid;
|
||||
}
|
||||
|
||||
@ -2361,6 +2366,8 @@ QImage QImage::convertToFormat(Format format, const QList<QRgb> &colorTable, Qt:
|
||||
|
||||
bool QImage::reinterpretAsFormat(Format format)
|
||||
{
|
||||
if (format <= Format_Invalid || format >= NImageFormats)
|
||||
return false;
|
||||
if (!d)
|
||||
return false;
|
||||
if (d->format == format)
|
||||
|
@ -345,6 +345,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
|
||||
{
|
||||
// Cannot be used with indexed formats or between formats with different pixel depths.
|
||||
Q_ASSERT(dst_format > QImage::Format_Indexed8);
|
||||
Q_ASSERT(dst_format < QImage::NImageFormats);
|
||||
Q_ASSERT(data->format > QImage::Format_Indexed8);
|
||||
const int destDepth = qt_depthForFormat(dst_format);
|
||||
if (data->depth < destDepth)
|
||||
@ -478,6 +479,7 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for
|
||||
{
|
||||
Q_ASSERT(data->format > QImage::Format_Indexed8);
|
||||
Q_ASSERT(dst_format > QImage::Format_Indexed8);
|
||||
Q_ASSERT(dst_format < QImage::NImageFormats);
|
||||
const int destDepth = qt_depthForFormat(dst_format);
|
||||
if (data->depth < destDepth)
|
||||
return false;
|
||||
@ -572,6 +574,7 @@ bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_f
|
||||
{
|
||||
Q_ASSERT(data->format >= QImage::Format_RGBX16FPx4);
|
||||
Q_ASSERT(dst_format >= QImage::Format_RGBX16FPx4);
|
||||
Q_ASSERT(dst_format < QImage::NImageFormats);
|
||||
const int destDepth = qt_depthForFormat(dst_format);
|
||||
if (data->depth < destDepth)
|
||||
return false;
|
||||
@ -682,6 +685,8 @@ static void convert_passthrough(QImageData *dest, const QImageData *src, Qt::Ima
|
||||
template<QImage::Format Format>
|
||||
static bool convert_passthrough_inplace(QImageData *data, Qt::ImageConversionFlags)
|
||||
{
|
||||
static_assert(Format > QImage::Format_Invalid);
|
||||
static_assert(Format < QImage::NImageFormats);
|
||||
data->format = Format;
|
||||
return true;
|
||||
}
|
||||
@ -839,6 +844,8 @@ static void convert_ARGB_to_RGBA(QImageData *dest, const QImageData *src, Qt::Im
|
||||
template<QImage::Format DestFormat>
|
||||
static bool convert_ARGB_to_RGBA_inplace(QImageData *data, Qt::ImageConversionFlags)
|
||||
{
|
||||
static_assert(DestFormat > QImage::Format_Invalid);
|
||||
static_assert(DestFormat < QImage::NImageFormats);
|
||||
Q_ASSERT(data->format == QImage::Format_ARGB32 || data->format == QImage::Format_ARGB32_Premultiplied);
|
||||
|
||||
const int pad = (data->bytes_per_line >> 2) - data->width;
|
||||
@ -885,6 +892,8 @@ static void convert_RGBA_to_ARGB(QImageData *dest, const QImageData *src, Qt::Im
|
||||
template<QImage::Format DestFormat>
|
||||
static bool convert_RGBA_to_ARGB_inplace(QImageData *data, Qt::ImageConversionFlags)
|
||||
{
|
||||
static_assert(DestFormat > QImage::Format_Invalid);
|
||||
static_assert(DestFormat < QImage::NImageFormats);
|
||||
Q_ASSERT(data->format == QImage::Format_RGBX8888 || data->format == QImage::Format_RGBA8888 || data->format == QImage::Format_RGBA8888_Premultiplied);
|
||||
|
||||
const int pad = (data->bytes_per_line >> 2) - data->width;
|
||||
@ -1233,6 +1242,8 @@ static void mask_alpha_converter(QImageData *dest, const QImageData *src, Qt::Im
|
||||
template<QImage::Format DestFormat>
|
||||
static bool mask_alpha_converter_inplace(QImageData *data, Qt::ImageConversionFlags)
|
||||
{
|
||||
static_assert(DestFormat > QImage::Format_Invalid);
|
||||
static_assert(DestFormat < QImage::NImageFormats);
|
||||
Q_ASSERT(data->format == QImage::Format_RGB32
|
||||
|| DestFormat == QImage::Format_RGB32
|
||||
|| DestFormat == QImage::Format_RGBX8888);
|
||||
|
@ -49,7 +49,7 @@ struct Q_GUI_EXPORT QImageData { // internal image data
|
||||
qreal devicePixelRatio;
|
||||
QList<QRgb> colortable;
|
||||
uchar *data;
|
||||
QImage::Format format;
|
||||
QImage::Format format; // invariants: > Format_Invalid, < NImageFormats
|
||||
qsizetype bytes_per_line;
|
||||
int ser_no; // serial number
|
||||
int detach_no;
|
||||
|
Loading…
x
Reference in New Issue
Block a user