diff options
author | Lars Knoll <lars.knoll@digia.com> | 2014-03-25 15:04:22 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-03-28 22:52:19 +0100 |
commit | c4d8734c504cf0f313245befa34501e7314b4cd1 (patch) | |
tree | fe7c21c9e75b2cfbb3d4c95eb04ccf56bae38ce7 /src/gui/painting/qdrawhelper_sse2.cpp | |
parent | 123ae472e2668a1f57f7c69a1a2a59336f83d06a (diff) |
Avoid out of bounds memory reads when scaling images
The calculation of the width/height required for the
scaling algorithm was prone to floating point rounding
issues, where the lower value got rounded down, the higher
one rounded up. This could lead to a situation where we
iterated over one more line/pixel in the line than we have
in the source image.
Correct this by passing the dimension of the source image into
the function and bounds checking the values before iterating.
Task-number: QTBUG-35927
Change-Id: If44b2235a479224660d508a0504fec40d724763a
Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
Diffstat (limited to 'src/gui/painting/qdrawhelper_sse2.cpp')
-rw-r--r-- | src/gui/painting/qdrawhelper_sse2.cpp | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index c37858d679..d02871c86d 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -568,7 +568,7 @@ const uint * QT_FASTCALL qt_fetch_radial_gradient_sse2(uint *buffer, const Opera } void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, + const uchar *srcPixels, int sbpl, int srch, const QRectF &targetRect, const QRectF &sourceRect, const QRect &clip, @@ -577,12 +577,12 @@ void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, if (const_alpha != 256) { // from qblendfunctions.cpp extern void qt_scale_image_argb32_on_argb32(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, + const uchar *srcPixels, int sbpl, int srch, const QRectF &targetRect, const QRectF &sourceRect, const QRect &clip, int const_alpha); - return qt_scale_image_argb32_on_argb32(destPixels, dbpl, srcPixels, sbpl, targetRect, sourceRect, clip, const_alpha); + return qt_scale_image_argb32_on_argb32(destPixels, dbpl, srcPixels, sbpl, srch, targetRect, sourceRect, clip, const_alpha); } qreal sx = targetRect.width() / (qreal) sourceRect.width(); @@ -651,6 +651,14 @@ void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, const __m128i alphaMask = _mm_set1_epi32(0xff000000); const __m128i ixVector = _mm_set1_epi32(4*ix); + // this bounds check here is required as floating point rounding above might in some cases lead to + // w/h values that are one pixel too large, falling outside of the valid image area. + int yend = (srcy + iy * (h - 1)) >> 16; + if (yend < 0 || yend >= srch) + --h; + int xend = (basex + ix * (w - 1)) >> 16; + if (xend < 0 || xend >= (int)(sbpl/sizeof(quint32))) + --w; while (h--) { const uint *src = (const quint32 *) (srcPixels + (srcy >> 16) * sbpl); |