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 <hermet@lottiefiles.com>

issue: https://github.com/thorvg/thorvg/issues/3102
This commit is contained in:
Jinny You 2025-01-16 14:43:17 +09:00 committed by Mira Grudzinska
parent 12b9c5fc53
commit c64624c8c8

View file

@ -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<int32_t>(image->stride);
int32_t sh = image->h;
int32_t dw = surface->stride;
int32_t sw = static_cast<int32_t>(image->w);
int32_t sh = static_cast<int32_t>(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<int32_t>(image->stride);
int32_t sh = image->h;
int32_t dw = surface->stride;
int32_t sw = static_cast<int32_t>(image->w);
int32_t sh = static_cast<int32_t>(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;
}
}
}