diff --git a/README.chromium b/README.chromium index ad40a378f..c5d59b89b 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: https://chromium.googlesource.com/libyuv/libyuv/ -Version: 1955 +Version: 1956 Revision: DEPS License: BSD-3-Clause License File: LICENSE diff --git a/include/libyuv/version.h b/include/libyuv/version.h index b913fe481..13d655c5c 100644 --- a/include/libyuv/version.h +++ b/include/libyuv/version.h @@ -11,6 +11,6 @@ #ifndef INCLUDE_LIBYUV_VERSION_H_ #define INCLUDE_LIBYUV_VERSION_H_ -#define LIBYUV_VERSION 1955 +#define LIBYUV_VERSION 1956 #endif // INCLUDE_LIBYUV_VERSION_H_ diff --git a/source/row_any.cc b/source/row_any.cc index 0d0a64354..566f584e5 100644 --- a/source/row_any.cc +++ b/source/row_any.cc @@ -27,7 +27,7 @@ extern "C" { // by the source type (e.g. ARGB) and the mask (last parameter), or by examining // the source code for how much the source pointers are advanced. -// Subsampled source needs to be increase by 1 of not even. +// Subsampled source needs to be increase by 1 if not even. #define SS(width, shift) (((width) + (1 << (shift)) - 1) >> (shift)) // Any 4 planes to 1 @@ -718,8 +718,8 @@ ANY21(SobelXYRow_Any_LSX, SobelXYRow_LSX, 0, 1, 1, 4, 15) #define ANY21S(NAMEANY, ANY_SIMD, SBPP, BPP, MASK) \ void NAMEANY(const uint8_t* src_yuy2, int stride_yuy2, uint8_t* dst_uv, \ int width) { \ - SIMD_ALIGNED(uint8_t vin[32 * 2]); \ - SIMD_ALIGNED(uint8_t vout[32]); \ + SIMD_ALIGNED(uint8_t vin[(MASK + 1) * SBPP * 2]); \ + SIMD_ALIGNED(uint8_t vout[(MASK + 1) * BPP]); \ memset(vin, 0, sizeof(vin)); /* for msan */ \ int awidth = (width + 1) / 2; \ int r = awidth & MASK; \ @@ -729,8 +729,9 @@ ANY21(SobelXYRow_Any_LSX, SobelXYRow_LSX, 0, 1, 1, 4, 15) } \ ptrdiff_t np = n; \ memcpy(vin, src_yuy2 + np * SBPP, r * SBPP); \ - memcpy(vin + 32, src_yuy2 + stride_yuy2 + np * SBPP, r * SBPP); \ - ANY_SIMD(vin, 32, vout, MASK + 1); \ + memcpy(vin + (MASK + 1) * SBPP, src_yuy2 + stride_yuy2 + np * SBPP, \ + r * SBPP); \ + ANY_SIMD(vin, (MASK + 1) * SBPP, vout, MASK + 1); \ memcpy(dst_uv + np * BPP, vout, r * BPP); \ } @@ -1917,23 +1918,23 @@ ANY12PT(SplitUVRow_16_Any_NEON, SplitUVRow_16_NEON, uint16_t, 2, 7) #undef ANY21CT // Any 1 to 3. Outputs RGB planes. -#define ANY13(NAMEANY, ANY_SIMD, BPP, MASK) \ - void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_r, uint8_t* dst_g, \ - uint8_t* dst_b, int width) { \ - SIMD_ALIGNED(uint8_t vin[16 * 3]); \ - SIMD_ALIGNED(uint8_t vout[16 * 3]); \ - memset(vin, 0, sizeof(vin)); /* for msan */ \ - int r = width & MASK; \ - int n = width & ~MASK; \ - if (n > 0) { \ - ANY_SIMD(src_ptr, dst_r, dst_g, dst_b, n); \ - } \ - ptrdiff_t np = n; \ - memcpy(vin, src_ptr + np * BPP, r * BPP); \ - ANY_SIMD(vin, vout, vout + 16, vout + 32, MASK + 1); \ - memcpy(dst_r + np, vout, r); \ - memcpy(dst_g + np, vout + 16, r); \ - memcpy(dst_b + np, vout + 32, r); \ +#define ANY13(NAMEANY, ANY_SIMD, BPP, MASK) \ + void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_r, uint8_t* dst_g, \ + uint8_t* dst_b, int width) { \ + SIMD_ALIGNED(uint8_t vin[(MASK + 1) * BPP]); \ + SIMD_ALIGNED(uint8_t vout[(MASK + 1) * 3]); \ + memset(vin, 0, sizeof(vin)); /* for msan */ \ + int r = width & MASK; \ + int n = width & ~MASK; \ + if (n > 0) { \ + ANY_SIMD(src_ptr, dst_r, dst_g, dst_b, n); \ + } \ + ptrdiff_t np = n; \ + memcpy(vin, src_ptr + np * BPP, r * BPP); \ + ANY_SIMD(vin, vout, vout + MASK + 1, vout + (MASK + 1) * 2, MASK + 1); \ + memcpy(dst_r + np, vout, r); \ + memcpy(dst_g + np, vout + MASK + 1, r); \ + memcpy(dst_b + np, vout + (MASK + 1) * 2, r); \ } #ifdef HAS_SPLITRGBROW_SSSE3 diff --git a/unit_test/convert_test.cc b/unit_test/convert_test.cc index 9d490aa7e..ecf28d6d8 100644 --- a/unit_test/convert_test.cc +++ b/unit_test/convert_test.cc @@ -2850,6 +2850,23 @@ TEST_F(LibYUVConvertTest, I21xToI420NoHeightOverflow) { free_aligned_buffer_page_end(dst_v); } +// Call YUY2ToNV12() with a width that is not a multiple of 32. Verify there is +// no stack buffer overflow in YUY2ToNVUVRow_Any_AVX2(). +TEST_F(LibYUVConvertTest, YUY2ToNV12Overflow) { + int width = 40 * 32 + 30; // 1310 + int height = 4; + int src_stride_yuy2 = width * 2; + align_buffer_page_end(src_yuy2, src_stride_yuy2 * height); + align_buffer_page_end(dst_y, width * height); + align_buffer_page_end(dst_uv, width * ((height + 1) / 2)); + memset(src_yuy2, 0xA5, src_stride_yuy2 * height); + EXPECT_EQ(0, YUY2ToNV12(src_yuy2, src_stride_yuy2, dst_y, width, dst_uv, + width, width, height)); + free_aligned_buffer_page_end(src_yuy2); + free_aligned_buffer_page_end(dst_y); + free_aligned_buffer_page_end(dst_uv); +} + #endif // !defined(LEAN_TESTS) } // namespace libyuv diff --git a/unit_test/planar_test.cc b/unit_test/planar_test.cc index 7eba494b7..86e7f740c 100644 --- a/unit_test/planar_test.cc +++ b/unit_test/planar_test.cc @@ -3277,6 +3277,24 @@ TEST_F(LibYUVPlanarTest, SplitRGBPlane_Opt) { free_aligned_buffer_page_end(dst_pixels_opt); } +// Call SplitRGBPlane() with a width that is not a multiple of 32. Verify there +// is no stack buffer overflow in SplitRGBRow_Any_AVX2(). +TEST_F(LibYUVPlanarTest, SplitRGBPlaneOverflow) { + int width = 1024 + 31; // 1055 + const int height = 2; + align_buffer_page_end(src_rgb, width * 3 * height); + align_buffer_page_end(dst_r, width * height); + align_buffer_page_end(dst_g, width * height); + align_buffer_page_end(dst_b, width * height); + memset(src_rgb, 0x5A, width * 3 * height); + SplitRGBPlane(src_rgb, width * 3, dst_r, width, dst_g, width, dst_b, width, + width, height); + free_aligned_buffer_page_end(src_rgb); + free_aligned_buffer_page_end(dst_r); + free_aligned_buffer_page_end(dst_g); + free_aligned_buffer_page_end(dst_b); +} + TEST_F(LibYUVPlanarTest, MergeARGBPlane_Opt) { const int kPixels = benchmark_width_ * benchmark_height_; align_buffer_page_end(src_pixels, kPixels * 4); @@ -3409,6 +3427,25 @@ TEST_F(LibYUVPlanarTest, SplitARGBPlane_Opt) { free_aligned_buffer_page_end(dst_pixels_opt); } +// Call SplitARGBPlane() with a width that is not a multiple of 16. Verify there +// is no stack buffer overflow in SplitXRGBRow_Any_AVX2(). +TEST_F(LibYUVPlanarTest, SplitARGBPlaneOverflow) { + int width = 1024 + 15; // 1039 + int height = 2; + align_buffer_page_end(src_argb, width * 4 * height); + align_buffer_page_end(dst_r, width * height); + align_buffer_page_end(dst_g, width * height); + align_buffer_page_end(dst_b, width * height); + memset(src_argb, 0x5A, width * 4 * height); + // dst_a == NULL selects SplitXRGBRow + SplitARGBPlane(src_argb, width * 4, dst_r, width, dst_g, width, dst_b, width, + NULL, 0, width, height); + free_aligned_buffer_page_end(src_argb); + free_aligned_buffer_page_end(dst_r); + free_aligned_buffer_page_end(dst_g); + free_aligned_buffer_page_end(dst_b); +} + TEST_F(LibYUVPlanarTest, MergeXRGBPlane_Opt) { const int kPixels = benchmark_width_ * benchmark_height_; align_buffer_page_end(src_pixels, kPixels * 4);