Correct vin/vout buffer sizes in ANY21S and ANY13

Tested:
libyuv_unittest --gtest_filter=LibYUVConvertTest.YUY2ToNV12Overflow
libyuv_unittest --gtest_filter=LibYUVPlanarTest.SplitRGBPlaneOverflow
libyuv_unittest --gtest_filter=LibYUVPlanarTest.SplitARGBPlaneOverflow

Bug: chromium:543078936
Change-Id: I45cc5ec912612b09ac720e3bdefa11c8ad503098
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8219514
Reviewed-by: Frank Barchard <fbarchard@google.com>
Commit-Queue: Wan-Teh Chang <wtc@google.com>
This commit is contained in:
Wan-Teh Chang 2026-08-10 13:53:17 -07:00 committed by libyuv-scoped@luci-project-accounts.iam.gserviceaccount.com
parent e2a1744681
commit c409140ff6
5 changed files with 79 additions and 24 deletions

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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);