mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2026-10-28 18:07:12 +08:00
ARGBScale: Fix signed integer overflow when scaling large heights
In ScaleARGBBilinearDown and ScaleARGBBilinearUp, adding dy to y can overflow signed 32-bit int when scaling down large height images (e.g., src_height = 32768 down to 2). Check if max_y - dy < y before adding dy to y to prevent signed integer overflow. R=wtc Fixed: 540206290, 539110937 Test: LibYUVScaleTest.ARGBScale_LargeHeightOverflow Change-Id: If353d002714481ce0018653798047066663f1fb9 Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8175358 Reviewed-by: Frank Barchard <fbarchard@google.com> Reviewed-by: Wan-Teh Chang <wtc@google.com> Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
This commit is contained in:
parent
79d22698bc
commit
2e58f4b971
@ -404,25 +404,23 @@ static int ScaleARGBBilinearDown(int src_width,
|
||||
if (!row)
|
||||
return 1;
|
||||
|
||||
const int max_y = (src_height - 1) << 16;
|
||||
if (y > max_y) {
|
||||
y = max_y;
|
||||
}
|
||||
const int64_t max_y = (int64_t)(src_height - 1) << 16;
|
||||
int64_t y64 = y;
|
||||
for (j = 0; j < dst_height; ++j) {
|
||||
int yi = y >> 16;
|
||||
if (y64 > max_y) {
|
||||
y64 = max_y;
|
||||
}
|
||||
int yi = (int)(y64 >> 16);
|
||||
const uint8_t* src = src_argb + yi * src_stride;
|
||||
if (filtering == kFilterLinear) {
|
||||
ScaleARGBFilterCols(dst_argb, src, dst_width, x, dx);
|
||||
} else {
|
||||
int yf = (y >> 8) & 255;
|
||||
int yf = (int)((y64 >> 8) & 255);
|
||||
InterpolateRow(row, src, src_stride, clip_src_width, yf);
|
||||
ScaleARGBFilterCols(dst_argb, row, dst_width, x, dx);
|
||||
}
|
||||
dst_argb += dst_stride;
|
||||
y += dy;
|
||||
if (y > max_y) {
|
||||
y = max_y;
|
||||
}
|
||||
y64 += dy;
|
||||
}
|
||||
free_aligned_buffer_64(row);
|
||||
}
|
||||
@ -450,7 +448,7 @@ static int ScaleARGBBilinearUp(int src_width,
|
||||
void (*ScaleARGBFilterCols)(uint8_t* dst_argb, const uint8_t* src_argb,
|
||||
int dst_width, int x, int dx) =
|
||||
filtering ? ScaleARGBFilterCols_C : ScaleARGBCols_C;
|
||||
const int max_y = (src_height - 1) << 16;
|
||||
const int64_t max_y = (int64_t)(src_height - 1) << 16;
|
||||
#if defined(HAS_INTERPOLATEROW_AVX2)
|
||||
if (TestCpuFlag(kCpuHasAVX2)) {
|
||||
InterpolateRow = InterpolateRow_Any_AVX2;
|
||||
@ -550,12 +548,13 @@ static int ScaleARGBBilinearUp(int src_width,
|
||||
#endif
|
||||
}
|
||||
|
||||
if (y > max_y) {
|
||||
y = max_y;
|
||||
int64_t y64 = y;
|
||||
if (y64 > max_y) {
|
||||
y64 = max_y;
|
||||
}
|
||||
|
||||
{
|
||||
int yi = y >> 16;
|
||||
int yi = (int)(y64 >> 16);
|
||||
const uint8_t* src = src_argb + yi * src_stride;
|
||||
|
||||
// Allocate 2 rows of ARGB.
|
||||
@ -578,31 +577,27 @@ static int ScaleARGBBilinearUp(int src_width,
|
||||
}
|
||||
|
||||
for (j = 0; j < dst_height; ++j) {
|
||||
yi = y >> 16;
|
||||
if (y64 > max_y) {
|
||||
y64 = max_y;
|
||||
}
|
||||
yi = (int)(y64 >> 16);
|
||||
if (yi != lasty) {
|
||||
if (y > max_y) {
|
||||
y = max_y;
|
||||
yi = y >> 16;
|
||||
src = src_argb + yi * src_stride;
|
||||
}
|
||||
if (yi != lasty) {
|
||||
ScaleARGBFilterCols(rowptr, src, dst_width, x, dx);
|
||||
rowptr += rowstride;
|
||||
rowstride = -rowstride;
|
||||
lasty = yi;
|
||||
if ((y + 65536) < max_y) {
|
||||
src += src_stride;
|
||||
}
|
||||
ScaleARGBFilterCols(rowptr, src, dst_width, x, dx);
|
||||
rowptr += rowstride;
|
||||
rowstride = -rowstride;
|
||||
lasty = yi;
|
||||
if ((y64 + 65536) < max_y) {
|
||||
src += src_stride;
|
||||
}
|
||||
}
|
||||
if (filtering == kFilterLinear) {
|
||||
InterpolateRow(dst_argb, rowptr, 0, dst_width * 4, 0);
|
||||
} else {
|
||||
int yf = (y >> 8) & 255;
|
||||
int yf = (int)((y64 >> 8) & 255);
|
||||
InterpolateRow(dst_argb, rowptr, rowstride, dst_width * 4, yf);
|
||||
}
|
||||
dst_argb += dst_stride;
|
||||
y += dy;
|
||||
y64 += dy;
|
||||
}
|
||||
free_aligned_buffer_64(row);
|
||||
}
|
||||
@ -630,7 +625,7 @@ static void ScaleARGBSimple(int src_width,
|
||||
void (*ScaleARGBCols)(uint8_t* dst_argb, const uint8_t* src_argb,
|
||||
int dst_width, int x, int dx) =
|
||||
(src_width >= 32768) ? ScaleARGBCols64_C : ScaleARGBCols_C;
|
||||
(void)src_height;
|
||||
const int64_t max_y = (int64_t)(src_height - 1) << 16;
|
||||
#if defined(HAS_SCALEARGBCOLS_SSE2)
|
||||
if (TestCpuFlag(kCpuHasSSE2) && src_width < 32768) {
|
||||
ScaleARGBCols = ScaleARGBCols_SSE2;
|
||||
@ -661,11 +656,15 @@ static void ScaleARGBSimple(int src_width,
|
||||
#endif
|
||||
}
|
||||
|
||||
int64_t y64 = y;
|
||||
for (j = 0; j < dst_height; ++j) {
|
||||
ScaleARGBCols(dst_argb, src_argb + (y >> 16) * src_stride, dst_width, x,
|
||||
if (y64 > max_y) {
|
||||
y64 = max_y;
|
||||
}
|
||||
ScaleARGBCols(dst_argb, src_argb + (y64 >> 16) * src_stride, dst_width, x,
|
||||
dx);
|
||||
dst_argb += dst_stride;
|
||||
y += dy;
|
||||
y64 += dy;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1474,7 +1474,9 @@ void ScalePlaneVertical(int src_height,
|
||||
void (*InterpolateRow)(uint8_t* dst_argb, const uint8_t* src_argb,
|
||||
ptrdiff_t src_stride, int dst_width,
|
||||
int source_y_fraction) = InterpolateRow_C;
|
||||
const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0;
|
||||
const int64_t max_y =
|
||||
(src_height > 1) ? (((int64_t)src_height - 1) << 16) - 1 : 0;
|
||||
int64_t y64 = y;
|
||||
int j;
|
||||
assert(bpp >= 1 && bpp <= 4);
|
||||
assert(src_height != 0);
|
||||
@ -1524,15 +1526,15 @@ void ScalePlaneVertical(int src_height,
|
||||
for (j = 0; j < dst_height; ++j) {
|
||||
int yi;
|
||||
int yf;
|
||||
if (y > max_y) {
|
||||
y = max_y;
|
||||
if (y64 > max_y) {
|
||||
y64 = max_y;
|
||||
}
|
||||
yi = y >> 16;
|
||||
yf = filtering ? ((y >> 8) & 255) : 0;
|
||||
yi = (int)(y64 >> 16);
|
||||
yf = filtering ? (int)((y64 >> 8) & 255) : 0;
|
||||
InterpolateRow(dst_argb, src_argb + yi * (ptrdiff_t)src_stride, src_stride,
|
||||
dst_width_bytes, yf);
|
||||
dst_argb += dst_stride;
|
||||
y += dy;
|
||||
y64 += dy;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1553,7 +1555,9 @@ void ScalePlaneVertical_16(int src_height,
|
||||
void (*InterpolateRow)(uint16_t* dst_argb, const uint16_t* src_argb,
|
||||
ptrdiff_t src_stride, int dst_width,
|
||||
int source_y_fraction) = InterpolateRow_16_C;
|
||||
const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0;
|
||||
const int64_t max_y =
|
||||
(src_height > 1) ? (((int64_t)src_height - 1) << 16) - 1 : 0;
|
||||
int64_t y64 = y;
|
||||
int j;
|
||||
assert(wpp >= 1 && wpp <= 2);
|
||||
assert(src_height != 0);
|
||||
@ -1592,15 +1596,15 @@ void ScalePlaneVertical_16(int src_height,
|
||||
for (j = 0; j < dst_height; ++j) {
|
||||
int yi;
|
||||
int yf;
|
||||
if (y > max_y) {
|
||||
y = max_y;
|
||||
if (y64 > max_y) {
|
||||
y64 = max_y;
|
||||
}
|
||||
yi = y >> 16;
|
||||
yf = filtering ? ((y >> 8) & 255) : 0;
|
||||
yi = (int)(y64 >> 16);
|
||||
yf = filtering ? (int)((y64 >> 8) & 255) : 0;
|
||||
InterpolateRow(dst_argb, src_argb + yi * (ptrdiff_t)src_stride, src_stride,
|
||||
dst_width_words, yf);
|
||||
dst_argb += dst_stride;
|
||||
y += dy;
|
||||
y64 += dy;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -597,4 +597,42 @@ TEST_F(LibYUVScaleTest, ARGBTest4x) {
|
||||
free_aligned_buffer_page_end(orig_pixels);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVScaleTest, ARGBScale_LargeHeightOverflow) {
|
||||
const int src_w = 4;
|
||||
const int src_h = 32767;
|
||||
align_buffer_page_end(orig_pixels, src_w * src_h * 4);
|
||||
align_buffer_page_end(dest_pixels, src_w * 2 * 4);
|
||||
memset(orig_pixels, 128, src_w * src_h * 4);
|
||||
|
||||
// Test both vertical-only scaling (dst_w == src_w) and 2D scaling (dst_w != src_w).
|
||||
for (int dst_w : {4, 2}) {
|
||||
int res = ARGBScale(orig_pixels, src_w * 4, src_w, src_h, dest_pixels,
|
||||
dst_w * 4, dst_w, 2, kFilterBilinear);
|
||||
EXPECT_EQ(0, res);
|
||||
|
||||
res = ARGBScale(orig_pixels, src_w * 4, src_w, -src_h, dest_pixels,
|
||||
dst_w * 4, dst_w, 2, kFilterBilinear);
|
||||
EXPECT_EQ(0, res);
|
||||
|
||||
res = ARGBScale(orig_pixels, src_w * 4, src_w, src_h, dest_pixels,
|
||||
dst_w * 4, dst_w, 2, kFilterLinear);
|
||||
EXPECT_EQ(0, res);
|
||||
|
||||
res = ARGBScale(orig_pixels, src_w * 4, src_w, -src_h, dest_pixels,
|
||||
dst_w * 4, dst_w, 2, kFilterLinear);
|
||||
EXPECT_EQ(0, res);
|
||||
|
||||
res = ARGBScale(orig_pixels, src_w * 4, src_w, src_h, dest_pixels,
|
||||
dst_w * 4, dst_w, 2, kFilterNone);
|
||||
EXPECT_EQ(0, res);
|
||||
|
||||
res = ARGBScale(orig_pixels, src_w * 4, src_w, -src_h, dest_pixels,
|
||||
dst_w * 4, dst_w, 2, kFilterNone);
|
||||
EXPECT_EQ(0, res);
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(dest_pixels);
|
||||
free_aligned_buffer_page_end(orig_pixels);
|
||||
}
|
||||
|
||||
} // namespace libyuv
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user