diff --git a/source/row_any.cc b/source/row_any.cc index 26d2ce3b9..0d0a64354 100644 --- a/source/row_any.cc +++ b/source/row_any.cc @@ -834,8 +834,12 @@ ANY21C(NV12ToRGB565Row_Any_LASX, NV12ToRGB565Row_LASX, 1, 1, 2, 2, 15) #define ANY21CT(NAMEANY, ANY_SIMD, UVSHIFT, DUVSHIFT, T, SBPP, BPP, MASK) \ void NAMEANY(const T* y_buf, const T* uv_buf, uint8_t* dst_ptr, \ const struct YuvConstants* yuvconstants, int width) { \ - SIMD_ALIGNED(T vin[16 * 2]); \ + SIMD_ALIGNED(T vin[32 * 2]); \ + static_assert(SS(MASK + 1, UVSHIFT) * SBPP * 2 <= sizeof(vin) / 2, \ + "vin buffer too small"); \ SIMD_ALIGNED(uint8_t vout[64]); \ + static_assert(SS(MASK + 1, DUVSHIFT) * BPP <= sizeof(vout), \ + "vout buffer too small"); \ memset(vin, 0, sizeof(vin)); /* for msan */ \ int r = width & MASK; \ int n = width & ~MASK; \ @@ -844,8 +848,8 @@ ANY21C(NV12ToRGB565Row_Any_LASX, NV12ToRGB565Row_LASX, 1, 1, 2, 2, 15) } \ ptrdiff_t np = n; \ memcpy(vin, y_buf + np, r * SBPP); \ - memcpy(vin + 16, uv_buf + 2 * (np >> UVSHIFT), SS(r, UVSHIFT) * SBPP * 2); \ - ANY_SIMD(vin, vin + 16, vout, yuvconstants, MASK + 1); \ + memcpy(vin + 32, uv_buf + 2 * (np >> UVSHIFT), SS(r, UVSHIFT) * SBPP * 2); \ + ANY_SIMD(vin, vin + 32, vout, yuvconstants, MASK + 1); \ memcpy(dst_ptr + (np >> DUVSHIFT) * BPP, vout, SS(r, DUVSHIFT) * BPP); \ } diff --git a/unit_test/convert_argb_test.cc b/unit_test/convert_argb_test.cc index 8411039d1..c65419823 100644 --- a/unit_test/convert_argb_test.cc +++ b/unit_test/convert_argb_test.cc @@ -2736,6 +2736,82 @@ TEST_F(LibYUVConvertTest, TestUYVYToARGB) { #endif } +// Call P010ToARGBMatrixFilter() with a width that is not a multiple of 16. +// Verify there is no stack buffer overflow in P410ToARGBRow_Any_AVX2(). +TEST_F(LibYUVConvertTest, P010ToARGBMatrixFilterOverflow) { + int width = 1024 + 15; // 1039 + int height = 4; + int dst_stride_argb = width * 4; + align_buffer_page_end_16(src_y, width * height); + align_buffer_page_end_16(src_uv, width * ((height + 1) / 2)); + align_buffer_page_end(dst_argb, dst_stride_argb * height); + memset(src_y, 0x02, width * height * sizeof(uint16_t)); + memset(src_uv, 0x02, width * ((height + 1) / 2) * sizeof(uint16_t)); + EXPECT_EQ(0, P010ToARGBMatrixFilter(src_y, width, src_uv, width, dst_argb, + dst_stride_argb, &kYuvI601Constants, + width, height, kFilterBilinear)); + free_aligned_buffer_page_end_16(src_y); + free_aligned_buffer_page_end_16(src_uv); + free_aligned_buffer_page_end(dst_argb); +} + +// Call P210ToARGBMatrixFilter() with a width that is not a multiple of 16. +// Verify there is no stack buffer overflow in P410ToARGBRow_Any_AVX2(). +TEST_F(LibYUVConvertTest, P210ToARGBMatrixFilterOverflow) { + int width = 1024 + 15; // 1039 + int height = 4; + int dst_stride_argb = width * 4; + align_buffer_page_end_16(src_y, width * height); + align_buffer_page_end_16(src_uv, width * height); + align_buffer_page_end(dst_argb, dst_stride_argb * height); + memset(src_y, 0x02, width * height * sizeof(uint16_t)); + memset(src_uv, 0x02, width * height * sizeof(uint16_t)); + EXPECT_EQ(0, P210ToARGBMatrixFilter(src_y, width, src_uv, width, dst_argb, + dst_stride_argb, &kYuvI601Constants, + width, height, kFilterBilinear)); + free_aligned_buffer_page_end_16(src_y); + free_aligned_buffer_page_end_16(src_uv); + free_aligned_buffer_page_end(dst_argb); +} + +// Call P010ToAR30MatrixFilter() with a width that is not a multiple of 16. +// Verify there is no stack buffer overflow in P410ToAR30Row_Any_AVX2(). +TEST_F(LibYUVConvertTest, P010ToAR30MatrixFilterOverflow) { + int width = 1024 + 15; // 1039 + int height = 4; + int dst_stride_argb = width * 4; + align_buffer_page_end_16(src_y, width * height); + align_buffer_page_end_16(src_uv, width * ((height + 1) / 2)); + align_buffer_page_end(dst_argb, dst_stride_argb * height); + memset(src_y, 0x02, width * height * sizeof(uint16_t)); + memset(src_uv, 0x02, width * ((height + 1) / 2) * sizeof(uint16_t)); + EXPECT_EQ(0, P010ToAR30MatrixFilter(src_y, width, src_uv, width, dst_argb, + dst_stride_argb, &kYuvI601Constants, + width, height, kFilterBilinear)); + free_aligned_buffer_page_end_16(src_y); + free_aligned_buffer_page_end_16(src_uv); + free_aligned_buffer_page_end(dst_argb); +} + +// Call P210ToAR30MatrixFilter(() with a width that is not a multiple of 16. +// Verify there is no stack buffer overflow in P410ToAR30Row_Any_AVX2(). +TEST_F(LibYUVConvertTest, P210ToAR30MatrixFilterOverflow) { + int width = 1024 + 15; // 1039 + int height = 4; + int dst_stride_ar30 = width * 4; + align_buffer_page_end_16(src_y, width * height); + align_buffer_page_end_16(src_uv, width * height); + align_buffer_page_end(dst_ar30, dst_stride_ar30 * height); + memset(src_y, 0x02, width * height * sizeof(uint16_t)); + memset(src_uv, 0x02, width * height * sizeof(uint16_t)); + EXPECT_EQ(0, P210ToAR30MatrixFilter(src_y, width, src_uv, width, dst_ar30, + dst_stride_ar30, &kYuvI601Constants, + width, height, kFilterBilinear)); + free_aligned_buffer_page_end_16(src_y); + free_aligned_buffer_page_end_16(src_uv); + free_aligned_buffer_page_end(dst_ar30); +} + #ifdef ENABLE_ROW_TESTS TEST_F(LibYUVConvertTest, TestARGBToUVMatrixRow_Opt) { const int kMaxWidth = 128;