From 6d25bdf34cb9232d4d2668e854d8eb6bc87b1f1d Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 17 Dec 2021 12:43:49 +0900 Subject: [PATCH] sw_engine raster: ++safety of the scaled image rasterization Prevent out of buffer boundary access. @Issues: https://github.com/Samsung/thorvg/pull/1119 Change-Id: I9d007b00f4193448fe2fd05194621190144ad7ce --- src/lib/sw_engine/tvgSwRaster.cpp | 145 +++++++++++++++----------- src/lib/sw_engine/tvgSwRasterTexmapInternal.h | 2 +- 2 files changed, 83 insertions(+), 64 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 9ef4cc0..56bc2f7 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -82,8 +82,8 @@ static inline uint32_t _halfScale(float scale) //Bilinear Interpolation static uint32_t _interpUpScaler(const uint32_t *img, uint32_t w, uint32_t h, float sx, float sy) { - auto rx = static_cast(sx); - auto ry = static_cast(sy); + auto rx = (uint32_t)(sx); + auto ry = (uint32_t)(sy); auto rx2 = rx + 1; if (rx2 >= w) rx2 = w - 1; auto ry2 = ry + 1; @@ -102,20 +102,23 @@ static uint32_t _interpUpScaler(const uint32_t *img, uint32_t w, uint32_t h, flo //2n x 2n Mean Kernel -static uint32_t _interpDownScaler(const uint32_t *img, uint32_t w, uint32_t h, uint32_t rX, uint32_t rY, uint32_t n) +static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t w, uint32_t h, uint32_t rx, uint32_t ry, uint32_t n) { - uint32_t c[4] = { 0 }; + uint32_t c[4] = {0, 0, 0, 0}; auto n2 = n * n; - auto src = img + rX - n + (rY - n) * w; - for (auto y = rY - n; y < rY + n; ++y) { + auto src = img + rx - n + (ry - n) * stride; + + for (auto y = ry - n; y < ry + n; ++y) { + if (y >= h) continue; auto p = src; - for (auto x = rX - n; x < rX + n; ++x, ++p) { + for (auto x = rx - n; x < rx + n; ++x, ++p) { + if (x >= w) continue; c[0] += *p >> 24; c[1] += (*p >> 16) & 0xff; c[2] += (*p >> 8) & 0xff; c[3] += *p & 0xff; } - src += w; + src += stride; } for (auto i = 0; i < 4; ++i) { c[i] = (c[i] >> 2) / n2; @@ -292,15 +295,15 @@ static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const //Center (Down-Scaled) if (image->scale < DOWN_SCALE_TOLERANCE) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto sy = static_cast(span->y * itransform->e22 + itransform->e23); + auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23); if (sy >= image->h) continue; auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x]; auto alpha = _multiplyAlpha(span->coverage, opacity); for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, ++cmp) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); + auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; - auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), alpha); + auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), alpha); auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } @@ -308,14 +311,14 @@ static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const //Center (Up-Scaled) } else { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto sy = static_cast(span->y * itransform->e22 + itransform->e23); - if (sy >= image->h) continue; + auto sy = span->y * itransform->e22 + itransform->e23; + if ((uint32_t)sy >= image->h) continue; auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x]; auto alpha = _multiplyAlpha(span->coverage, opacity); for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, ++cmp) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); - if (sx >= image->w) continue; + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha); auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); @@ -335,22 +338,22 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i //Center (Down-Scaled) if (image->scale < DOWN_SCALE_TOLERANCE) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto sy = static_cast(span->y * itransform->e22 + itransform->e23); + auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23); if (sy >= image->h) continue; auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x]; if (span->coverage == 255) { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, ++cmp) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); + auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; - auto tmp = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), blendMethod(*cmp)); + auto tmp = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), blendMethod(*cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } else { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, ++cmp) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); + auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; - auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), span->coverage); + auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), span->coverage); auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } @@ -359,21 +362,21 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i //Center (Up-Scaled) } else { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto sy = static_cast(span->y * itransform->e22 + itransform->e23); - if (sy >= image->h) continue; + auto sy = span->y * itransform->e22 + itransform->e23; + if ((uint32_t)sy >= image->h) continue; auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x]; if (span->coverage == 255) { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, ++cmp) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); - if (sx >= image->w) continue; + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; auto tmp = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), blendMethod(*cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } else { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, ++cmp) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); - if (sx >= image->w) continue; + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), span->coverage); auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); @@ -392,27 +395,27 @@ static bool _rasterScaledTranslucentRleRGBAImage(SwSurface* surface, const SwIma //Center (Down-Scaled) if (image->scale < DOWN_SCALE_TOLERANCE) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto sy = static_cast(span->y * itransform->e22 + itransform->e23); + auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23); if (sy >= image->h) continue; auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto alpha = _multiplyAlpha(span->coverage, opacity); for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); + auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; - auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), alpha); + auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), alpha); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } } //Center (Up-Scaled) } else { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto sy = static_cast(span->y * itransform->e22 + itransform->e23); - if (sy >= image->h) continue; + auto sy = span->y * itransform->e22 + itransform->e23; + if ((uint32_t)sy >= image->h) continue; auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto alpha = _multiplyAlpha(span->coverage, opacity); for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); - if (sx >= image->w) continue; + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } @@ -429,21 +432,21 @@ static bool _rasterScaledRleRGBAImage(SwSurface* surface, const SwImage* image, //Center (Down-Scaled) if (image->scale < DOWN_SCALE_TOLERANCE) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto sy = static_cast(span->y * itransform->e22 + itransform->e23); + auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23); if (sy >= image->h) continue; auto dst = &surface->buffer[span->y * surface->stride + span->x]; if (span->coverage == 255) { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); + auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; - auto src = _interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale); + auto src = _interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } } else { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); + auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; - auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), span->coverage); + auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), span->coverage); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } } @@ -451,20 +454,20 @@ static bool _rasterScaledRleRGBAImage(SwSurface* surface, const SwImage* image, //Center (Up-Scaled) } else { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto sy = static_cast(span->y * itransform->e22 + itransform->e23); - if (sy >= image->h) continue; + auto sy = span->y * itransform->e22 + itransform->e23; + if ((uint32_t)sy >= image->h) continue; auto dst = &surface->buffer[span->y * surface->stride + span->x]; if (span->coverage == 255) { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); - if (sx >= image->w) continue; + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; auto src = _interpUpScaler(image->data, image->w, image->h, sx, sy); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } } else { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); - if (sx >= image->w) continue; + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), span->coverage); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } @@ -663,13 +666,15 @@ static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const Sw // Down-Scaled if (image->scale < DOWN_SCALE_TOLERANCE) { for (auto y = region.min.y; y < region.max.y; ++y) { + auto sy = (uint32_t)(y * itransform->e22 + itransform->e23); + if (sy >= image->h) continue; auto dst = dbuffer; auto cmp = cbuffer; - auto sy = static_cast(y * itransform->e22 + itransform->e23); for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) { + auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); + if (sx >= image->w) continue; auto alpha = _multiplyAlpha(opacity, blendMethod(*cmp)); - auto sx = static_cast(x * itransform->e11 + itransform->e13); - auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), alpha); + auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), alpha); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } dbuffer += surface->stride; @@ -678,12 +683,14 @@ static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const Sw // Up-Scaled } else { for (auto y = region.min.y; y < region.max.y; ++y) { + auto sy = y * itransform->e22 + itransform->e23; + if ((uint32_t)sy >= image->h) continue; auto dst = dbuffer; auto cmp = cbuffer; - auto sy = fabsf(y * itransform->e22 + itransform->e23); for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) { + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; auto alpha = _multiplyAlpha(opacity, blendMethod(*cmp)); - auto sx = fabsf(x * itransform->e11 + itransform->e13); auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } @@ -705,12 +712,14 @@ static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* imag // Down-Scaled if (image->scale < DOWN_SCALE_TOLERANCE) { for (auto y = region.min.y; y < region.max.y; ++y) { + auto sy = (uint32_t)(y * itransform->e22 + itransform->e23); + if (sy >= image->h) continue; auto dst = dbuffer; auto cmp = cbuffer; - auto sy = static_cast(y * itransform->e22 + itransform->e23); for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); - auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), blendMethod(*cmp)); + auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); + if (sx >= image->w) continue; + auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), blendMethod(*cmp)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } dbuffer += surface->stride; @@ -719,11 +728,13 @@ static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* imag // Up-Scaled } else { for (auto y = region.min.y; y < region.max.y; ++y) { + auto sy = y * itransform->e22 + itransform->e23; + if ((uint32_t)sy >= image->h) continue; auto dst = dbuffer; auto cmp = cbuffer; - auto sy = fabsf(y * itransform->e22 + itransform->e23); for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) { - auto sx = fabsf(x * itransform->e11 + itransform->e13); + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), blendMethod(*cmp)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } @@ -742,11 +753,13 @@ static bool _rasterScaledTranslucentRGBAImage(SwSurface* surface, const SwImage* // Down-Scaled if (image->scale < DOWN_SCALE_TOLERANCE) { for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { - auto sy = static_cast(y * itransform->e22 + itransform->e23); + auto sy = (uint32_t)(y * itransform->e22 + itransform->e23); + if (sy >= image->h) continue; auto dst = dbuffer; for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); - auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), opacity); + auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); + if (sx >= image->w) continue; + auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), opacity); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } } @@ -754,9 +767,11 @@ static bool _rasterScaledTranslucentRGBAImage(SwSurface* surface, const SwImage* } else { for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { auto sy = fabsf(y * itransform->e22 + itransform->e23); + if (sy >= image->h) continue; auto dst = dbuffer; for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { - auto sx = fabsf(x * itransform->e11 + itransform->e13); + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), opacity); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } @@ -773,21 +788,25 @@ static bool _rasterScaledRGBAImage(SwSurface* surface, const SwImage* image, con // Down-Scaled if (image->scale < DOWN_SCALE_TOLERANCE) { for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { - auto sy = static_cast(y * itransform->e22 + itransform->e23); + auto sy = (uint32_t)(y * itransform->e22 + itransform->e23); + if (sy >= image->h) continue; auto dst = dbuffer; for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { - auto sx = static_cast(x * itransform->e11 + itransform->e13); - auto src = _interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale); + auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); + if (sx >= image->w) continue; + auto src = _interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } } // Up-Scaled } else { for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { - auto sy = fabsf(y * itransform->e22 + itransform->e23); + auto sy = y * itransform->e22 + itransform->e23; + if ((uint32_t)sy >= image->h) continue; auto dst = dbuffer; for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { - auto sx = fabsf(x * itransform->e11 + itransform->e13); + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; auto src = _interpUpScaler(image->data, image->w, image->h, sx, sy); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } diff --git a/src/lib/sw_engine/tvgSwRasterTexmapInternal.h b/src/lib/sw_engine/tvgSwRasterTexmapInternal.h index f7203e1..782c8f6 100644 --- a/src/lib/sw_engine/tvgSwRasterTexmapInternal.h +++ b/src/lib/sw_engine/tvgSwRasterTexmapInternal.h @@ -62,7 +62,7 @@ if (x1 < minx) x1 = minx; if (x2 > maxx) x2 = maxx; - + //Anti-Aliasing frames ay = y - aaSpans->yStart; if (aaSpans->lines[ay].x[0] > x1) aaSpans->lines[ay].x[0] = x1; -- 2.7.4