Make I420DataSize trigger a crash in case of int overflow.

Bug: chromium:371686447
Fixes: chromium:371686447
Change-Id: Icd4ef5f1edc54853445bb1542eff62e354655368
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/371900
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43588}
This commit is contained in:
Tommi 2024-12-17 14:35:08 +01:00 committed by WebRTC LUCI CQ
parent 69f8321b67
commit 0dec0897f1
3 changed files with 38 additions and 2 deletions

View File

@ -69,6 +69,7 @@ rtc_library("video_frame") {
"..:video_track_source_constraints", "..:video_track_source_constraints",
"../../rtc_base:checks", "../../rtc_base:checks",
"../../rtc_base:refcount", "../../rtc_base:refcount",
"../../rtc_base:safe_conversions",
"../../rtc_base:timeutils", "../../rtc_base:timeutils",
"../../rtc_base/memory:aligned_malloc", "../../rtc_base/memory:aligned_malloc",
"../../rtc_base/system:rtc_export", "../../rtc_base/system:rtc_export",

View File

@ -13,6 +13,7 @@
#include <algorithm> #include <algorithm>
#include <cstdint> #include <cstdint>
#include <limits>
#include <utility> #include <utility>
#include "api/make_ref_counted.h" #include "api/make_ref_counted.h"
@ -21,6 +22,7 @@
#include "api/video/video_rotation.h" #include "api/video/video_rotation.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/memory/aligned_malloc.h" #include "rtc_base/memory/aligned_malloc.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "third_party/libyuv/include/libyuv/convert.h" #include "third_party/libyuv/include/libyuv/convert.h"
#include "third_party/libyuv/include/libyuv/planar_functions.h" #include "third_party/libyuv/include/libyuv/planar_functions.h"
#include "third_party/libyuv/include/libyuv/rotate.h" #include "third_party/libyuv/include/libyuv/rotate.h"
@ -33,8 +35,17 @@ namespace webrtc {
namespace { namespace {
int I420DataSize(int height, int stride_y, int stride_u, int stride_v) { // Do the size calculation using 64bit integers and check for int overflow.
return stride_y * height + (stride_u + stride_v) * ((height + 1) / 2); int I420DataSize(int64_t height,
int64_t stride_y,
int64_t stride_u,
int64_t stride_v) {
RTC_DCHECK(height >= 0 && height <= std::numeric_limits<int>::max());
RTC_DCHECK(stride_y >= 0 && stride_y <= std::numeric_limits<int>::max());
RTC_DCHECK(stride_u >= 0 && stride_u <= std::numeric_limits<int>::max());
RTC_DCHECK(stride_v >= 0 && stride_v <= std::numeric_limits<int>::max());
return rtc::checked_cast<int>(stride_y * height +
(stride_u + stride_v) * ((height + 1) / 2));
} }
} // namespace } // namespace

View File

@ -18,6 +18,7 @@
#include "api/video/i420_buffer.h" #include "api/video/i420_buffer.h"
#include "api/video/video_frame.h" #include "api/video/video_frame.h"
#include "common_video/libyuv/include/webrtc_libyuv.h" #include "common_video/libyuv/include/webrtc_libyuv.h"
#include "rtc_base/logging.h"
#include "test/frame_utils.h" #include "test/frame_utils.h"
#include "test/gmock.h" #include "test/gmock.h"
#include "test/gtest.h" #include "test/gtest.h"
@ -383,4 +384,27 @@ TEST(I420WeightedPSNRTest, SmokeTest) {
/*abs_error=*/0.001); /*abs_error=*/0.001);
} }
#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
// Check that we catch int overflow if invalid dimensions get passed to
// `I420Buffer::Create()`.
TEST_F(TestLibYuv, I420DimensionsTooLarge) {
// Dimensions large enough to cause overflow.
constexpr int kWidth = 0xFFFF;
constexpr int kHeight = 0xAAB0;
// Sanity check for this test. This calculation, which is part of what
// `I420Buffer::Create()` will do, should cause an `int` overflow.
static_assert(
(int64_t{kWidth} * int64_t{kHeight}) > std::numeric_limits<int>::max(),
"");
// The Y plane is the image width * height, while the strides of the U and V
// planes are half the width.
const int stride_uv = (kWidth + 1) / 2;
EXPECT_DEATH(I420Buffer::Create(kWidth, kHeight, /*stride_y=*/kWidth,
/*stride_u=*/stride_uv,
/*stride_v=*/stride_uv),
"IsValueInRangeForNumericType");
}
#endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
} // namespace webrtc } // namespace webrtc