mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2026-06-15 00:16:08 +08:00
[libyuv] Fix security vulnerabilities in ScalePlane and ARGBAffineRow_C
This CL addresses two security findings related to integer overflows: 1. Input validation in ScalePlane, ScalePlane_16, and ScalePlane_12: Added checks to reject invalid dimensions (e.g. width <= 0, height == 0) and dimensions larger than 32768 (or smaller than -32768 for height). This prevents FixedDiv signed integer overflows that can lead to division by zero/overflow crashes (SIGFPE on x86) or incorrect step calculations. 2. Stride overflow in ARGBAffineRow_C: Casted pointer arithmetic operands to ptrdiff_t before multiplication (y * stride and x * 4) to ensure 64-bit calculations, preventing signed 32-bit integer overflow when calculating source pixel offsets. Added unit tests to verify the input validation in ScalePlane functions. Test: libyuv_unittest --gtest_filter=*InvalidInputs* Test: libyuv_unittest --gtest_filter=*Scale* Test: libyuv_unittest --gtest_filter=*TestAffine* Bug: None TAG=agy CONV=0e990960-611b-4f38-94ec-24e79b66242e R=wtc@google.com Change-Id: I252af47a98e45dff8bb5f06308c3739c6eead741 Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7886217 Reviewed-by: Wan-Teh Chang <wtc@google.com> Commit-Queue: Frank Barchard <fbarchard@google.com>
This commit is contained in:
parent
c98edcc8dc
commit
ef08f21f6d
@ -3663,7 +3663,8 @@ void ARGBAffineRow_C(const uint8_t* src_argb,
|
||||
int x = (int)(uv[0]);
|
||||
int y = (int)(uv[1]);
|
||||
*(uint32_t*)(dst_argb) =
|
||||
*(const uint32_t*)(src_argb + y * src_argb_stride + x * 4);
|
||||
*(const uint32_t*)(src_argb + (ptrdiff_t)y * src_argb_stride +
|
||||
(ptrdiff_t)x * 4);
|
||||
dst_argb += 4;
|
||||
uv[0] += uv_dudv[2];
|
||||
uv[1] += uv_dudv[3];
|
||||
|
||||
@ -1947,6 +1947,14 @@ int ScalePlane(const uint8_t* src,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
enum FilterMode filtering) {
|
||||
// Reject dimensions larger than 32768 (or smaller than -32768 for height).
|
||||
// This prevents FixedDiv signed integer overflows that can lead to division
|
||||
// by zero/overflow crashes (SIGFPE on x86) or incorrect step calculations.
|
||||
if (!src || src_width <= 0 || src_height == 0 ||
|
||||
src_width > 32768 || src_height < -32768 || src_height > 32768 ||
|
||||
!dst || dst_width <= 0 || dst_height <= 0) {
|
||||
return -1;
|
||||
}
|
||||
// Simplify filtering when possible.
|
||||
filtering = ScaleFilterReduce(src_width, src_height, dst_width, dst_height,
|
||||
filtering);
|
||||
@ -2047,6 +2055,14 @@ int ScalePlane_16(const uint16_t* src,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
enum FilterMode filtering) {
|
||||
// Reject dimensions larger than 32768 (or smaller than -32768 for height).
|
||||
// This prevents FixedDiv signed integer overflows that can lead to division
|
||||
// by zero/overflow crashes (SIGFPE on x86) or incorrect step calculations.
|
||||
if (!src || src_width <= 0 || src_height == 0 ||
|
||||
src_width > 32768 || src_height < -32768 || src_height > 32768 ||
|
||||
!dst || dst_width <= 0 || dst_height <= 0) {
|
||||
return -1;
|
||||
}
|
||||
// Simplify filtering when possible.
|
||||
filtering = ScaleFilterReduce(src_width, src_height, dst_width, dst_height,
|
||||
filtering);
|
||||
@ -2151,6 +2167,14 @@ int ScalePlane_12(const uint16_t* src,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
enum FilterMode filtering) {
|
||||
// Reject dimensions larger than 32768 (or smaller than -32768 for height).
|
||||
// This prevents FixedDiv signed integer overflows that can lead to division
|
||||
// by zero/overflow crashes (SIGFPE on x86) or incorrect step calculations.
|
||||
if (!src || src_width <= 0 || src_height == 0 ||
|
||||
src_width > 32768 || src_height < -32768 || src_height > 32768 ||
|
||||
!dst || dst_width <= 0 || dst_height <= 0) {
|
||||
return -1;
|
||||
}
|
||||
// Simplify filtering when possible.
|
||||
filtering = ScaleFilterReduce(src_width, src_height, dst_width, dst_height,
|
||||
filtering);
|
||||
|
||||
@ -636,4 +636,53 @@ TEST_F(LibYUVScaleTest, ScalePlaneVertical_IntStrideOverflow) {
|
||||
delete[] dst;
|
||||
}
|
||||
|
||||
TEST_F(LibYUVScaleTest, ScalePlane_InvalidInputs) {
|
||||
uint8_t src[16] = {0};
|
||||
uint8_t dst[16] = {0};
|
||||
|
||||
// NULL src/dst
|
||||
EXPECT_EQ(-1, ScalePlane(nullptr, 4, 4, 4, dst, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane(src, 4, 4, 4, nullptr, 4, 4, 4, kFilterNone));
|
||||
|
||||
// Width/height <= 0 (except src_height which can be negative but not 0)
|
||||
EXPECT_EQ(-1, ScalePlane(src, 4, 0, 4, dst, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane(src, 4, -1, 4, dst, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane(src, 4, 4, 0, dst, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane(src, 4, 4, 4, dst, 4, 0, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane(src, 4, 4, 4, dst, 4, -1, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane(src, 4, 4, 4, dst, 4, 4, 0, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane(src, 4, 4, 4, dst, 4, 4, -1, kFilterNone));
|
||||
|
||||
// Width/height too large (> 32768)
|
||||
EXPECT_EQ(-1, ScalePlane(src, 4, 32769, 4, dst, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane(src, 4, 4, 32769, dst, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane(src, 4, 4, -32769, dst, 4, 4, 4, kFilterNone));
|
||||
|
||||
// Valid edge cases
|
||||
EXPECT_EQ(0, ScalePlane(src, 4, 1, 1, dst, 4, 1, 1, kFilterNone));
|
||||
EXPECT_EQ(0, ScalePlane(src, 4, 1, -1, dst, 4, 1, 1, kFilterNone));
|
||||
}
|
||||
|
||||
TEST_F(LibYUVScaleTest, ScalePlane_16_InvalidInputs) {
|
||||
uint16_t src[16] = {0};
|
||||
uint16_t dst[16] = {0};
|
||||
|
||||
EXPECT_EQ(-1, ScalePlane_16(nullptr, 4, 4, 4, dst, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane_16(src, 4, 4, 4, nullptr, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane_16(src, 4, 0, 4, dst, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane_16(src, 4, 32769, 4, dst, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane_16(src, 4, 4, -32769, dst, 4, 4, 4, kFilterNone));
|
||||
}
|
||||
|
||||
TEST_F(LibYUVScaleTest, ScalePlane_12_InvalidInputs) {
|
||||
uint16_t src[16] = {0};
|
||||
uint16_t dst[16] = {0};
|
||||
|
||||
EXPECT_EQ(-1, ScalePlane_12(nullptr, 4, 4, 4, dst, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane_12(src, 4, 4, 4, nullptr, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane_12(src, 4, 0, 4, dst, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane_12(src, 4, 32769, 4, dst, 4, 4, 4, kFilterNone));
|
||||
EXPECT_EQ(-1, ScalePlane_12(src, 4, 4, -32769, dst, 4, 4, 4, kFilterNone));
|
||||
}
|
||||
|
||||
} // namespace libyuv
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user