diff --git a/source/scale.cc b/source/scale.cc index ade50df2c..29424ae71 100644 --- a/source/scale.cc +++ b/source/scale.cc @@ -1219,6 +1219,11 @@ static int ScalePlaneBilinearUp(int src_width, const uint8_t* src_ptr, uint8_t* dst_ptr, enum FilterMode filtering) { + assert(src_width > 0); + assert(src_height > 0); + assert(dst_width > 0); + assert(dst_height > 0); + int j; // Initial source x/y coordinate and step values as 16.16 fixed point. int x = 0; @@ -1234,6 +1239,7 @@ static int ScalePlaneBilinearUp(int src_width, filtering ? ScaleFilterCols_C : ScaleCols_C; ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y, &dx, &dy); + assert(dy <= 65536); src_width = Abs(src_width); #if defined(HAS_INTERPOLATEROW_AVX2) @@ -1327,22 +1333,27 @@ static int ScalePlaneBilinearUp(int src_width, src += src_stride; } + // 2-row rolling buffer: + // rowptr and (rowptr + rowstride) hold the scaled rows for yi and yi + 1. + // Because dy <= 65536 (dy <= 1.0 in 16.16), yi advances in unit steps. + // When yi != lasty: + // 1. Scale the next source row into the older buffer (rowptr). + // 2. Swap buffer pointers (rowptr += rowstride; rowstride = -rowstride;) + // so rowptr points to yi and (rowptr + rowstride) points to yi + 1. + // 3. Advance src by 1 row if row yi + 2 exists ((y + 65536) < max_y), + // otherwise clamp src at (src_height - 1) to avoid reading out of bounds. for (j = 0; j < dst_height; ++j) { + if (y > max_y) { + y = max_y; + } yi = y >> 16; if (yi != lasty) { - if (y > max_y) { - y = max_y; - yi = y >> 16; - src = src_ptr + yi * src_stride; - } - if (yi != lasty) { - ScaleFilterCols(rowptr, src, dst_width, x, dx); - rowptr += rowstride; - rowstride = -rowstride; - lasty = yi; - if ((y + 65536) < max_y) { - src += src_stride; - } + ScaleFilterCols(rowptr, src, dst_width, x, dx); + rowptr += rowstride; + rowstride = -rowstride; + lasty = yi; + if ((y + 65536) < max_y) { + src += src_stride; } } if (filtering == kFilterLinear) { @@ -1705,6 +1716,11 @@ static int ScalePlaneBilinearUp_16(int src_width, const uint16_t* src_ptr, uint16_t* dst_ptr, enum FilterMode filtering) { + assert(src_width > 0); + assert(src_height > 0); + assert(dst_width > 0); + assert(dst_height > 0); + int j; // Initial source x/y coordinate and step values as 16.16 fixed point. int x = 0; @@ -1720,6 +1736,7 @@ static int ScalePlaneBilinearUp_16(int src_width, filtering ? ScaleFilterCols_16_C : ScaleCols_16_C; ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y, &dx, &dy); + assert(dy <= 65536); src_width = Abs(src_width); #if defined(HAS_INTERPOLATEROW_16_SSSE3) @@ -1768,6 +1785,7 @@ static int ScalePlaneBilinearUp_16(int src_width, } #endif } + if (y > max_y) { y = max_y; } @@ -1793,22 +1811,27 @@ static int ScalePlaneBilinearUp_16(int src_width, src += src_stride; } + // 2-row rolling buffer: + // rowptr and (rowptr + rowstride) hold the scaled rows for yi and yi + 1. + // Because dy <= 65536 (dy <= 1.0 in 16.16), yi advances in unit steps. + // When yi != lasty: + // 1. Scale the next source row into the older buffer (rowptr). + // 2. Swap buffer pointers (rowptr += rowstride; rowstride = -rowstride;) + // so rowptr points to yi and (rowptr + rowstride) points to yi + 1. + // 3. Advance src by 1 row if row yi + 2 exists ((y + 65536) < max_y), + // otherwise clamp src at (src_height - 1) to avoid reading out of bounds. for (j = 0; j < dst_height; ++j) { + if (y > max_y) { + y = max_y; + } yi = y >> 16; if (yi != lasty) { - if (y > max_y) { - y = max_y; - yi = y >> 16; - src = src_ptr + yi * src_stride; - } - if (yi != lasty) { - ScaleFilterCols(rowptr, src, dst_width, x, dx); - rowptr += rowstride; - rowstride = -rowstride; - lasty = yi; - if ((y + 65536) < max_y) { - src += src_stride; - } + ScaleFilterCols(rowptr, src, dst_width, x, dx); + rowptr += rowstride; + rowstride = -rowstride; + lasty = yi; + if ((y + 65536) < max_y) { + src += src_stride; } } if (filtering == kFilterLinear) { diff --git a/source/scale_argb.cc b/source/scale_argb.cc index 9c2ac29c9..8dda11797 100644 --- a/source/scale_argb.cc +++ b/source/scale_argb.cc @@ -441,6 +441,12 @@ static int ScaleARGBBilinearUp(int src_width, int y, int dy, enum FilterMode filtering) { + assert(src_width > 0); + assert(src_height > 0); + assert(dst_width > 0); + assert(dst_height > 0); + assert(dy <= 65536); + int j; void (*InterpolateRow)(uint8_t* dst_argb, const uint8_t* src_argb, ptrdiff_t src_stride, int dst_width, @@ -576,6 +582,15 @@ static int ScaleARGBBilinearUp(int src_width, src += src_stride; } + // 2-row rolling buffer: + // rowptr and (rowptr + rowstride) hold the scaled rows for yi and yi + 1. + // Because dy <= 65536 (dy <= 1.0 in 16.16), yi advances in unit steps. + // When yi != lasty: + // 1. Scale the next source row into the older buffer (rowptr). + // 2. Swap buffer pointers (rowptr += rowstride; rowstride = -rowstride;) + // so rowptr points to yi and (rowptr + rowstride) points to yi + 1. + // 3. Advance src by 1 row if row yi + 2 exists ((y64 + 65536) < max_y), + // otherwise clamp src at (src_height - 1) to avoid reading out of bounds. for (j = 0; j < dst_height; ++j) { if (y64 > max_y) { y64 = max_y; diff --git a/source/scale_uv.cc b/source/scale_uv.cc index e20e708be..c0dc4b84c 100644 --- a/source/scale_uv.cc +++ b/source/scale_uv.cc @@ -463,6 +463,12 @@ static int ScaleUVBilinearUp(int src_width, int y, int dy, enum FilterMode filtering) { + assert(src_width > 0); + assert(src_height > 0); + assert(dst_width > 0); + assert(dst_height > 0); + assert(dy <= 65536); + int j; void (*InterpolateRow)(uint8_t* dst_uv, const uint8_t* src_uv, ptrdiff_t src_stride, int dst_width, @@ -575,22 +581,27 @@ static int ScaleUVBilinearUp(int src_width, src += src_stride; } + // 2-row rolling buffer: + // rowptr and (rowptr + rowstride) hold the scaled rows for yi and yi + 1. + // Because dy <= 65536 (dy <= 1.0 in 16.16), yi advances in unit steps. + // When yi != lasty: + // 1. Scale the next source row into the older buffer (rowptr). + // 2. Swap buffer pointers (rowptr += rowstride; rowstride = -rowstride;) + // so rowptr points to yi and (rowptr + rowstride) points to yi + 1. + // 3. Advance src by 1 row if row yi + 2 exists ((y + 65536) < max_y), + // otherwise clamp src at (src_height - 1) to avoid reading out of bounds. for (j = 0; j < dst_height; ++j) { + if (y > max_y) { + y = max_y; + } yi = y >> 16; if (yi != lasty) { - if (y > max_y) { - y = max_y; - yi = y >> 16; - src = src_uv + yi * src_stride; - } - if (yi != lasty) { - ScaleUVFilterCols(rowptr, src, dst_width, x, dx); - rowptr += rowstride; - rowstride = -rowstride; - lasty = yi; - if ((y + 65536) < max_y) { - src += src_stride; - } + ScaleUVFilterCols(rowptr, src, dst_width, x, dx); + rowptr += rowstride; + rowstride = -rowstride; + lasty = yi; + if ((y + 65536) < max_y) { + src += src_stride; } } if (filtering == kFilterLinear) {