QPicture: fix crash for malformed picture

A file with the correct QPicture magic bytes, but shorter than a full
QPicture file header, could cause the header decoder to access memory
out of bounds. Add a size check to avoid.

As a driveby, generally harden the parsing against malformed files.

[ChangeLog][QtGui][QPicture] Fix crash reading malformed picture file

Task-number: QTBUG-71208
Change-Id: I86eb1f915ca9b3a4b91c7433036d76ed6061e2f0
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
bb10
Eirik Aavitsland 2018-10-17 16:22:11 +02:00
parent 7f60940fbe
commit 6599c1f758
1 changed files with 12 additions and 11 deletions

View File

@ -636,7 +636,7 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
if (d->formatMajor <= 5) {
s >> ia >> i_8;
painter->drawPolygon(ia, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
a.clear();
ia.clear();
} else {
s >> a >> i_8;
painter->drawPolygon(a, i_8 ? Qt::WindingFill : Qt::OddEvenFill);
@ -647,10 +647,10 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
s >> ia;
QPainterPath path;
Q_ASSERT(ia.size() == 4);
path.moveTo(ia.at(0));
path.cubicTo(ia.at(1), ia.at(2), ia.at(3));
path.moveTo(ia.value(0));
path.cubicTo(ia.value(1), ia.value(2), ia.value(3));
painter->strokePath(path, painter->pen());
a.clear();
ia.clear();
}
break;
case QPicturePrivate::PdcDrawText:
@ -730,7 +730,7 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
int index;
s >> r >> index >> sr;
Q_ASSERT(index < d->pixmap_list.size());
pixmap = d->pixmap_list.at(index);
pixmap = d->pixmap_list.value(index);
} else {
s >> r >> pixmap >> sr;
}
@ -744,7 +744,7 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
int index;
s >> r >> index >> p;
Q_ASSERT(index < d->pixmap_list.size());
pixmap = d->pixmap_list.at(index);
pixmap = d->pixmap_list.value(index);
} else {
s >> r >> pixmap >> p;
}
@ -765,7 +765,7 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
int index;
s >> r >> index >> sr >> ul;
Q_ASSERT(index < d->image_list.size());
image = d->image_list.at(index);
image = d->image_list.value(index);
} else {
s >> r >> image >> sr >> ul;
}
@ -817,7 +817,7 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
int index;
s >> index;
Q_ASSERT(index < d->pen_list.size());
pen = d->pen_list.at(index);
pen = d->pen_list.value(index);
} else {
s >> pen;
}
@ -828,7 +828,7 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
int index;
s >> index;
Q_ASSERT(index < d->brush_list.size());
brush = d->brush_list.at(index);
brush = d->brush_list.value(index);
} else {
s >> brush;
}
@ -910,7 +910,7 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
break;
default:
qWarning("QPicture::play: Invalid command %d", c);
if (len) // skip unknown command
if (len > 0) // skip unknown command
s.device()->seek(s.device()->pos()+len);
}
#if defined(QT_DEBUG)
@ -1075,7 +1075,8 @@ bool QPicturePrivate::checkFormat()
char mf_id[4]; // picture header tag
s.readRawData(mf_id, 4); // read actual tag
if (memcmp(mf_id, qt_mfhdr_tag, 4) != 0) { // wrong header id
int bufSize = pictb.buffer().size();
if (memcmp(mf_id, qt_mfhdr_tag, 4) != 0 || bufSize < 12) { // wrong header id or size
qWarning("QPicturePaintEngine::checkFormat: Incorrect header");
pictb.close();
return false;