| Index: media/mojo/common/mojo_shared_buffer_video_frame.cc
|
| diff --git a/media/mojo/common/mojo_shared_buffer_video_frame.cc b/media/mojo/common/mojo_shared_buffer_video_frame.cc
|
| index 13b42ad447acace9ce9a7db783f25d15e7381ca8..1772059ffb27d029a830554b71304a48eca473b0 100644
|
| --- a/media/mojo/common/mojo_shared_buffer_video_frame.cc
|
| +++ b/media/mojo/common/mojo_shared_buffer_video_frame.cc
|
| @@ -8,6 +8,8 @@
|
| #include "base/callback.h"
|
| #include "base/compiler_specific.h"
|
| #include "base/logging.h"
|
| +#include "base/numerics/safe_conversions.h"
|
| +#include "base/numerics/safe_math.h"
|
|
|
| namespace media {
|
|
|
| @@ -72,6 +74,52 @@ scoped_refptr<MojoSharedBufferVideoFrame> MojoSharedBufferVideoFrame::Create(
|
| return nullptr;
|
| }
|
|
|
| + // Validate that the offsets and strides fit in the buffer.
|
| + //
|
| + // We can rely on coded_size.GetArea() being relatively small (compared to the
|
| + // range of an int) due to the IsValidConfig() check above.
|
| + //
|
| + // TODO(sandersd): Allow non-sequential formats.
|
| + if (NumPlanes(format) != 3) {
|
| + DLOG(ERROR) << __func__ << " " << VideoPixelFormatToString(format)
|
| + << " is not supported; only YUV formats are allowed";
|
| + return nullptr;
|
| + }
|
| +
|
| + if (y_stride < 0 || u_stride < 0 || v_stride < 0) {
|
| + DLOG(ERROR) << __func__ << " Invalid stride";
|
| + return nullptr;
|
| + }
|
| +
|
| + // Safe given sizeof(size_t) >= sizeof(int32_t).
|
| + size_t y_stride_size_t = y_stride;
|
| + size_t u_stride_size_t = u_stride;
|
| + size_t v_stride_size_t = v_stride;
|
| + if (y_stride_size_t < RowBytes(kYPlane, format, coded_size.width()) ||
|
| + u_stride_size_t < RowBytes(kUPlane, format, coded_size.width()) ||
|
| + v_stride_size_t < RowBytes(kVPlane, format, coded_size.width())) {
|
| + DLOG(ERROR) << __func__ << " Invalid stride";
|
| + return nullptr;
|
| + }
|
| +
|
| + base::CheckedNumeric<size_t> y_rows =
|
| + Rows(kYPlane, format, coded_size.height());
|
| + base::CheckedNumeric<size_t> u_rows =
|
| + Rows(kUPlane, format, coded_size.height());
|
| + base::CheckedNumeric<size_t> v_rows =
|
| + Rows(kVPlane, format, coded_size.height());
|
| +
|
| + base::CheckedNumeric<size_t> y_bound = y_rows * y_stride + y_offset;
|
| + base::CheckedNumeric<size_t> u_bound = u_rows * u_stride + u_offset;
|
| + base::CheckedNumeric<size_t> v_bound = v_rows * v_stride + v_offset;
|
| +
|
| + if (!y_bound.IsValid() || !u_bound.IsValid() || !v_bound.IsValid() ||
|
| + y_bound.ValueOrDie() > data_size || u_bound.ValueOrDie() > data_size ||
|
| + v_bound.ValueOrDie() > data_size) {
|
| + DLOG(ERROR) << __func__ << " Invalid offset";
|
| + return nullptr;
|
| + }
|
| +
|
| // Now allocate the frame and initialize it.
|
| scoped_refptr<MojoSharedBufferVideoFrame> frame(
|
| new MojoSharedBufferVideoFrame(format, coded_size, visible_rect,
|
|
|