Fixed potential access violation in QPixmap::copy() for <32 bit pixmaps.

QImage is supposed to maintain the invariant that each scan-line begins
on a 4-byte boundary, so we need to verify that this is the case before
using the optimized path of short-cutting QImage::copy() by referencing
the source image's bits directly.

Task-number: QTBUG-14766
Change-Id: I0a178aeb2f34cc64f98deae9470b55b5c53fcb06
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
This commit is contained in:
Samuel Rødal 2013-02-25 09:58:34 +01:00 committed by The Qt Project
parent 7ee4ab1463
commit 711773776e
2 changed files with 13 additions and 2 deletions

View File

@ -239,8 +239,9 @@ QImage QRasterPlatformPixmap::toImage(const QRect &rect) const
return image; return image;
QRect clipped = rect.intersected(QRect(0, 0, w, h)); QRect clipped = rect.intersected(QRect(0, 0, w, h));
if (d % 8 == 0) const uint du = uint(d);
return QImage(image.scanLine(clipped.y()) + clipped.x() * (d / 8), if ((du % 8 == 0) && (((uint(clipped.x()) * du)) % 32 == 0))
return QImage(image.scanLine(clipped.y()) + clipped.x() * (du / 8),
clipped.width(), clipped.height(), clipped.width(), clipped.height(),
image.bytesPerLine(), image.format()); image.bytesPerLine(), image.format());
else else

View File

@ -167,6 +167,8 @@ private slots:
void scaled_QTBUG19157(); void scaled_QTBUG19157();
void detachOnLoad_QTBUG29639(); void detachOnLoad_QTBUG29639();
void copyOnNonAlignedBoundary();
}; };
static bool lenientCompare(const QPixmap &actual, const QPixmap &expected) static bool lenientCompare(const QPixmap &actual, const QPixmap &expected)
@ -1503,5 +1505,13 @@ void tst_QPixmap::detachOnLoad_QTBUG29639()
QVERIFY(a.toImage() != b.toImage()); QVERIFY(a.toImage() != b.toImage());
} }
void tst_QPixmap::copyOnNonAlignedBoundary()
{
QImage img(8, 2, QImage::Format_RGB16);
QPixmap pm1 = QPixmap::fromImage(img, Qt::NoFormatConversion);
QPixmap pm2 = pm1.copy(QRect(5, 0, 3, 2)); // When copying second line: 2 bytes too many are read which might cause an access violation.
}
QTEST_MAIN(tst_QPixmap) QTEST_MAIN(tst_QPixmap)
#include "tst_qpixmap.moc" #include "tst_qpixmap.moc"