Compare commits

..

14 Commits

Author SHA1 Message Date
5989bba56a GIT_SILENT Upgrade ECM and KF5 version requirements for 5.56.0 release. 2019-03-02 13:27:12 +00:00
20100a1e0e ras: fix crash on broken files
Replace QVector::operator[] with QVector::value() since we can't know for
sure the values will be on range so use value() that gives us a 0 if the
index is not on range

oss-fuzz/13462
2019-03-01 23:33:35 +01:00
297b168a52 Use auto here too 2019-02-28 23:03:25 +01:00
f1c6c15b06 compile without foreach
Summary: compile without foreach

Reviewers: dfaure, apol

Reviewed By: apol

Subscribers: apol, kde-frameworks-devel

Tags: #frameworks

Differential Revision: https://phabricator.kde.org/D19317
2019-02-28 23:02:41 +01:00
156bac5e54 ras: protect the palette QVector too
oss-fuzz/13068
2019-02-13 23:50:36 +01:00
d79c11d280 ras: tweak max file check
better to do - 32 than + 32 otherwise we may overflow

oss-fuzz/13017
2019-02-11 22:57:33 +01:00
aeec934839 xcf: Fix uninitialized memory use on broken documents
oss-fuzz/12871
2019-02-08 23:27:03 +01:00
0c4f2f8e62 add const, helps understand the function better 2019-02-08 23:07:56 +01:00
4a8da73f0e ras: tweak max size that "fits" in a QVector
oss-fuzz/12951
2019-02-07 22:14:22 +01:00
039d7d8fbe ras: don't assert because we try to allicate a huge vector
oss-fuzz/12915
2019-02-06 22:06:58 +01:00
b072484dbb ras: Protect against divide by zero
oss-fuzz/12905
2019-02-05 19:51:24 +01:00
bad90cea4b xcf: Don't divide by 0
oss-fuzz/12815
2019-02-03 14:06:33 +01:00
a51cbd865f tga: fail gracefully if readRawData errors
oss-fuzz/12818
2019-02-03 13:49:11 +01:00
1a31500e55 ras: fail gracefully on height*width*bpp > length
oss-fuzz/12822
2019-02-03 13:38:44 +01:00
9 changed files with 65 additions and 23 deletions

View File

@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.5)
project(KImageFormats)
include(FeatureSummary)
find_package(ECM 5.55.0 NO_MODULE)
find_package(ECM 5.56.0 NO_MODULE)
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://projects.kde.org/projects/kdesupport/extra-cmake-modules")
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES)
@ -45,7 +45,7 @@ set_package_properties(OpenEXR PROPERTIES
TYPE OPTIONAL
PURPOSE "Required for the QImage plugin for OpenEXR images"
)
add_definitions(-DQT_NO_FOREACH)
add_subdirectory(src)
if (BUILD_TESTING)
add_subdirectory(autotests)

View File

@ -127,7 +127,8 @@ int main(int argc, char ** argv)
<< "Starting basic read tests for "
<< suffix << " images *********\n";
foreach (QFileInfo fi, imgdir.entryInfoList()) {
const QFileInfoList lstImgDir = imgdir.entryInfoList();
for (const QFileInfo &fi : lstImgDir) {
int suffixPos = fi.filePath().count() - suffix.count();
QString inputfile = fi.filePath();
QString expfile = fi.filePath().replace(suffixPos, suffix.count(), QStringLiteral("png"));

View File

@ -73,8 +73,8 @@ int main(int argc, char ** argv)
QTextStream(stdout) << "********* "
<< "Starting basic write tests for "
<< suffix << " images *********\n";
foreach (QFileInfo fi, imgdir.entryInfoList()) {
const QFileInfoList lstImgDir = imgdir.entryInfoList();
for (const QFileInfo &fi : lstImgDir) {
int suffixPos = fi.filePath().count() - suffix.count();
QString pngfile = fi.filePath().replace(suffixPos, suffix.count(), QStringLiteral("png"));
QString pngfilename = QFileInfo(pngfile).fileName();

View File

@ -173,9 +173,9 @@ static QDataStream &operator<< (QDataStream &s, const QList<PicChannel> &channel
return s;
}
static bool readRow(QDataStream &stream, QRgb *row, quint16 width, QList<PicChannel> channels)
static bool readRow(QDataStream &stream, QRgb *row, quint16 width, const QList<PicChannel> &channels)
{
Q_FOREACH(const PicChannel &channel, channels) {
for(const PicChannel &channel : channels) {
auto readPixel = [&] (QDataStream &str) -> QRgb {
quint8 red = 0;
if (channel.code & RED) {
@ -242,7 +242,7 @@ bool SoftimagePICHandler::read(QImage *image)
}
QImage::Format fmt = QImage::Format_RGB32;
Q_FOREACH(const PicChannel &channel, m_channels) {
for (const PicChannel &channel : qAsConst(m_channels)) {
if (channel.size != 8) {
// we cannot read images that do not come in bytes
qDebug() << "Channel size was" << channel.size;
@ -388,8 +388,8 @@ void SoftimagePICHandler::setOption(ImageOption option, const QVariant &value)
break;
case Description: {
m_description.clear();
QStringList entries = value.toString().split(QStringLiteral("\n\n"));
Q_FOREACH(const QString entry, entries) {
const QStringList entries = value.toString().split(QStringLiteral("\n\n"));
for (const QString &entry : entries) {
if (entry.startsWith(QStringLiteral("Description: "))) {
m_description = entry.mid(13).simplified().toUtf8();
}
@ -425,7 +425,7 @@ QVariant SoftimagePICHandler::option(ImageOption option) const
return QString();
case ImageFormat:
if (const_cast<SoftimagePICHandler*>(this)->readChannels()) {
Q_FOREACH (const PicChannel &channel, m_channels) {
for (const PicChannel &channel : qAsConst(m_channels)) {
if (channel.code & ALPHA) {
return QImage::Format_ARGB32;
}

View File

@ -102,6 +102,13 @@ static bool IsSupported(const RasHeader &head)
static bool LoadRAS(QDataStream &s, const RasHeader &ras, QImage &img)
{
s.device()->seek(RasHeader::SIZE);
// QVector uses some extra space for stuff, hence the 32 here suggested by thiago
if (ras.ColorMapLength > std::numeric_limits<int>::max() - 32) {
qWarning() << "LoadRAS() unsupported image color map length in file header" << ras.ColorMapLength;
return false;
}
// Read palette if needed.
QVector<quint8> palette(ras.ColorMapLength);
if (ras.ColorMapType == 1) {
@ -110,9 +117,26 @@ static bool LoadRAS(QDataStream &s, const RasHeader &ras, QImage &img)
}
}
const int bpp = ras.Depth / 8;
if (ras.Height == 0) {
return false;
}
if (bpp == 0) {
return false;
}
if (ras.Length / ras.Height / bpp < ras.Width) {
qWarning() << "LoadRAS() mistmatch between height and width" << ras.Width << ras.Height << ras.Length << ras.Depth;
return false;
}
// QVector uses some extra space for stuff, hence the 32 here suggested by thiago
if (ras.Length > std::numeric_limits<int>::max() - 32) {
qWarning() << "LoadRAS() unsupported image length in file header" << ras.Length;
return false;
}
// each line must be a factor of 16 bits, so they may contain padding
// this will be 1 if padding required, 0 otherwise
int paddingrequired = (ras.Width * (ras.Depth / 8) % 2);
const int paddingrequired = (ras.Width * bpp % 2);
// qDebug() << "paddingrequired: " << paddingrequired;
// don't trust ras.Length
@ -122,7 +146,7 @@ static bool LoadRAS(QDataStream &s, const RasHeader &ras, QImage &img)
while (! s.atEnd()) {
s >> input[i];
// I guess we need to find out if we're at the end of a line
if (paddingrequired && i != 0 && !(i % (ras.Width * (ras.Depth / 8)))) {
if (paddingrequired && i != 0 && !(i % (ras.Width * bpp))) {
s >> input[i];
}
i++;
@ -140,9 +164,9 @@ static bool LoadRAS(QDataStream &s, const RasHeader &ras, QImage &img)
quint8 red, green, blue;
for (quint32 y = 0; y < ras.Height; y++) {
for (quint32 x = 0; x < ras.Width; x++) {
red = palette[(int)input[y * ras.Width + x]];
green = palette[(int)input[y * ras.Width + x] + (ras.ColorMapLength / 3)];
blue = palette[(int)input[y * ras.Width + x] + 2 * (ras.ColorMapLength / 3)];
red = palette.value((int)input[y * ras.Width + x]);
green = palette.value((int)input[y * ras.Width + x] + (ras.ColorMapLength / 3));
blue = palette.value((int)input[y * ras.Width + x] + 2 * (ras.ColorMapLength / 3));
img.setPixel(x, y, qRgb(red, green, blue));
}
}

View File

@ -206,6 +206,9 @@ static bool LoadTGA(QDataStream &s, const TgaHeader &tga, QImage &img)
// @todo Support palettes in other formats!
const int size = 3 * tga.colormap_length;
const int dataRead = s.readRawData(palette, size);
if (dataRead < 0) {
return false;
}
if (dataRead < size) {
memset(&palette[dataRead], 0, size - dataRead);
}
@ -260,6 +263,10 @@ static bool LoadTGA(QDataStream &s, const TgaHeader &tga, QImage &img)
} else {
// Read raw image.
const int dataRead = s.readRawData((char *)image, size);
if (dataRead < 0) {
free(image);
return false;
}
if (dataRead < size) {
memset(&image[dataRead], 0, size - dataRead);
}

View File

@ -901,7 +901,7 @@ void XCFImageFormat::setPalette(XCFImage &xcf_image, QImage &image)
void XCFImageFormat::assignImageBytes(Layer &layer, uint i, uint j)
{
QImage &image = layer.image_tiles[j][i];
uchar *tile = layer.tile;
const uchar *tile = layer.tile;
const int width = image.width();
const int height = image.height();
const int bytesPerLine = image.bytesPerLine();
@ -1063,6 +1063,13 @@ bool XCFImageFormat::loadLevel(QDataStream &xcf_io, Layer &layer, qint32 bpp)
xcf_io >> width >> height >> offset;
if (offset == 0) {
// offset 0 with rowsxcols != 0 is probably an error since it means we have tiles
// without data but just clear the bits for now instead of returning false
for (uint j = 0; j < layer.nrows; j++) {
for (uint i = 0; i < layer.ncols; i++) {
layer.image_tiles[j][i].fill(Qt::transparent);
}
}
return true;
}
@ -2214,7 +2221,7 @@ void XCFImageFormat::mergeRGBToRGB(Layer &layer, uint i, uint j, int k, int l,
uchar new_r, new_g, new_b, new_a;
new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
float src_ratio = (float)src_a / new_a;
const float src_ratio = new_a == 0 ? 1.0 : (float)src_a / new_a;
float dst_ratio = 1.0 - src_ratio;
new_r = (uchar)(src_ratio * src_r + dst_ratio * dst_r + EPSILON);
@ -2373,7 +2380,7 @@ void XCFImageFormat::mergeGrayAToGray(Layer &layer, uint i, uint j, int k, int l
uchar new_a = OPAQUE_OPACITY;
float src_ratio = (float)src_a / new_a;
const float src_ratio = new_a == 0 ? 1.0 : (float)src_a / new_a;
float dst_ratio = 1.0 - src_ratio;
uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
@ -2546,7 +2553,7 @@ void XCFImageFormat::mergeGrayAToRGB(Layer &layer, uint i, uint j, int k, int l,
uchar new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
float src_ratio = (float)src_a / new_a;
const float src_ratio = new_a == 0 ? 1.0 : (float)src_a / new_a;
float dst_ratio = 1.0 - src_ratio;
uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);

View File

@ -64,11 +64,13 @@ int main(int argc, char **argv)
if (parser.isSet(listformats)) {
QTextStream out(stdout);
out << "Input formats:\n";
foreach (const QByteArray &fmt, QImageReader::supportedImageFormats()) {
const auto lstReaderSupportedFormats = QImageReader::supportedImageFormats();
for (const QByteArray &fmt : lstReaderSupportedFormats) {
out << " " << fmt << '\n';
}
out << "Output formats:\n";
foreach (const QByteArray &fmt, QImageWriter::supportedImageFormats()) {
const auto lstWriterSupportedFormats = QImageWriter::supportedImageFormats();
for (const QByteArray &fmt : lstWriterSupportedFormats) {
out << " " << fmt << '\n';
}
return 0;

View File

@ -72,7 +72,8 @@ int main(int argc, char **argv)
if (parser.isSet(listformats)) {
QTextStream out(stdout);
out << "File formats:\n";
foreach (const QByteArray &fmt, QImageReader::supportedImageFormats()) {
const auto lstSupportedFormats = QImageReader::supportedImageFormats();
for (const auto &fmt : lstSupportedFormats) {
out << " " << fmt << '\n';
}
return 0;