From c64624c8c801edf47dc0979a52e21e6d91e76843 Mon Sep 17 00:00:00 2001 From: Jinny You Date: Thu, 16 Jan 2025 14:43:17 +0900 Subject: [PATCH] sw_engine: Fix buffer overflow in texture mapping rasterizer Fix heap buffer overflow in texture mapping rasterizer by adding proper bounds checking for texture coordinates. This prevents accessing memory outside of the allocated image buffer during texture sampling and interpolation. Co-Authored-By: Hermet Park issue: https://github.com/thorvg/thorvg/issues/3102 --- src/renderer/sw_engine/tvgSwRasterTexmap.h | 68 +++++++++------------- 1 file changed, 29 insertions(+), 39 deletions(-) diff --git a/src/renderer/sw_engine/tvgSwRasterTexmap.h b/src/renderer/sw_engine/tvgSwRasterTexmap.h index 8e85f45e..0ae44099 100644 --- a/src/renderer/sw_engine/tvgSwRasterTexmap.h +++ b/src/renderer/sw_engine/tvgSwRasterTexmap.h @@ -87,9 +87,8 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage float _xa = xa, _xb = xb, _ua = ua, _va = va; auto sbuf = image->buf32; auto dbuf = surface->buf32; - int32_t sw = static_cast(image->stride); - int32_t sh = image->h; - int32_t dw = surface->stride; + int32_t sw = static_cast(image->w); + int32_t sh = static_cast(image->h); int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay; int32_t vv = 0, uu = 0; int32_t minx = INT32_MAX, maxx = 0; @@ -146,7 +145,7 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage u = _ua + dx * _dudx; v = _va + dx * _dvdx; - buf = dbuf + ((y * dw) + x1); + buf = dbuf + ((y * surface->stride) + x1); x = x1; @@ -154,32 +153,32 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage //Draw horizontal line while (x++ < x2) { uu = (int) u; - if (uu >= sw) continue; vv = (int) v; - if (vv >= sh) continue; + + if ((uint32_t) uu >= image->w || (uint32_t) vv >= image->h) continue; ar = (int)(255 * (1 - modff(u, &iptr))); ab = (int)(255 * (1 - modff(v, &iptr))); iru = uu + 1; irv = vv + 1; - px = *(sbuf + (vv * sw) + uu); + px = *(sbuf + (vv * image->stride) + uu); /* horizontal interpolate */ if (iru < sw) { /* right pixel */ - int px2 = *(sbuf + (vv * sw) + iru); + int px2 = *(sbuf + (vv * image->stride) + iru); px = INTERPOLATE(px, px2, ar); } /* vertical interpolate */ if (irv < sh) { /* bottom pixel */ - int px2 = *(sbuf + (irv * sw) + uu); + int px2 = *(sbuf + (irv * image->stride) + uu); /* horizontal interpolate */ if (iru < sw) { /* bottom right pixel */ - int px3 = *(sbuf + (irv * sw) + iru); + int px3 = *(sbuf + (irv * image->stride) + iru); px2 = INTERPOLATE(px2, px3, ar); } px = INTERPOLATE(px, px2, ab); @@ -190,39 +189,37 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage //Step UV horizontally u += _dudx; v += _dvdx; - //range over? - if ((uint32_t)(int32_t)v >= image->h) break; } } else { //Draw horizontal line while (x++ < x2) { uu = (int) u; - if (uu >= sw) continue; vv = (int) v; - if (vv >= sh) continue; + + if ((uint32_t) uu >= image->w || (uint32_t) vv >= image->h) continue; ar = (int)(255 * (1 - modff(u, &iptr))); ab = (int)(255 * (1 - modff(v, &iptr))); iru = uu + 1; irv = vv + 1; - px = *(sbuf + (vv * sw) + uu); + px = *(sbuf + (vv * image->stride) + uu); /* horizontal interpolate */ if (iru < sw) { /* right pixel */ - int px2 = *(sbuf + (vv * sw) + iru); + int px2 = *(sbuf + (vv * image->stride) + iru); px = INTERPOLATE(px, px2, ar); } /* vertical interpolate */ if (irv < sh) { /* bottom pixel */ - int px2 = *(sbuf + (irv * sw) + uu); + int px2 = *(sbuf + (irv * image->stride) + uu); /* horizontal interpolate */ if (iru < sw) { /* bottom right pixel */ - int px3 = *(sbuf + (irv * sw) + iru); + int px3 = *(sbuf + (irv * image->stride) + iru); px2 = INTERPOLATE(px2, px3, ar); } px = INTERPOLATE(px, px2, ab); @@ -234,8 +231,6 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage //Step UV horizontally u += _dudx; v += _dvdx; - //range over? - if ((uint32_t)(int32_t)v >= image->h) break; } } } @@ -264,9 +259,8 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, float _xa = xa, _xb = xb, _ua = ua, _va = va; auto sbuf = image->buf32; auto dbuf = surface->buf32; - int32_t sw = static_cast(image->stride); - int32_t sh = image->h; - int32_t dw = surface->stride; + int32_t sw = static_cast(image->w); + int32_t sh = static_cast(image->h); int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay; int32_t vv = 0, uu = 0; int32_t minx = INT32_MAX, maxx = 0; @@ -328,7 +322,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, u = _ua + dx * _dudx; v = _va + dx * _dvdx; - buf = dbuf + ((y * dw) + x1); + buf = dbuf + ((y * surface->stride) + x1); x = x1; @@ -338,32 +332,32 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, //Draw horizontal line while (x++ < x2) { uu = (int) u; - if (uu >= sw) continue; vv = (int) v; - if (vv >= sh) continue; + + if ((uint32_t) uu >= image->w || (uint32_t) vv >= image->h) continue; ar = (int)(255.0f * (1.0f - modff(u, &iptr))); ab = (int)(255.0f * (1.0f - modff(v, &iptr))); iru = uu + 1; irv = vv + 1; - px = *(sbuf + (vv * sw) + uu); + px = *(sbuf + (vv * image->stride) + uu); /* horizontal interpolate */ if (iru < sw) { /* right pixel */ - int px2 = *(sbuf + (vv * sw) + iru); + int px2 = *(sbuf + (vv * image->stride) + iru); px = INTERPOLATE(px, px2, ar); } /* vertical interpolate */ if (irv < sh) { /* bottom pixel */ - int px2 = *(sbuf + (irv * sw) + uu); + int px2 = *(sbuf + (irv * image->stride) + uu); /* horizontal interpolate */ if (iru < sw) { /* bottom right pixel */ - int px3 = *(sbuf + (irv * sw) + iru); + int px3 = *(sbuf + (irv * image->stride) + iru); px2 = INTERPOLATE(px2, px3, ar); } px = INTERPOLATE(px, px2, ab); @@ -381,8 +375,6 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, //Step UV horizontally u += _dudx; v += _dvdx; - //range over? - if ((uint32_t)(int32_t)v >= image->h) break; } } else { //Draw horizontal line @@ -390,30 +382,30 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, uu = (int) u; vv = (int) v; + if ((uint32_t) uu >= image->w || (uint32_t) vv >= image->h) continue; + ar = (int)(255.0f * (1.0f - modff(u, &iptr))); ab = (int)(255.0f * (1.0f - modff(v, &iptr))); iru = uu + 1; irv = vv + 1; - if (vv >= sh) continue; - px = *(sbuf + (vv * sw) + uu); /* horizontal interpolate */ if (iru < sw) { /* right pixel */ - int px2 = *(sbuf + (vv * sw) + iru); + int px2 = *(sbuf + (vv * image->stride) + iru); px = INTERPOLATE(px, px2, ar); } /* vertical interpolate */ if (irv < sh) { /* bottom pixel */ - int px2 = *(sbuf + (irv * sw) + uu); + int px2 = *(sbuf + (irv * image->stride) + uu); /* horizontal interpolate */ if (iru < sw) { /* bottom right pixel */ - int px3 = *(sbuf + (irv * sw) + iru); + int px3 = *(sbuf + (irv * image->stride) + iru); px2 = INTERPOLATE(px2, px3, ar); } px = INTERPOLATE(px, px2, ab); @@ -431,8 +423,6 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, //Step UV horizontally u += _dudx; v += _dvdx; - //range over? - if ((uint32_t)(int32_t)v >= image->h) break; } } }