Chromium Code Reviews| 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..fdbb139ab68a3b2913a89ada3160415630c4fcdb 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,53 @@ 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.ValueOrDefault(0) > data_size || |
|
dcheng
2017/06/08 09:41:08
Nit: use ValueOrDie() here (since we just checked
sandersd (OOO until July 31)
2017/06/08 20:10:09
Done.
|
| + u_bound.ValueOrDefault(0) > data_size || |
| + v_bound.ValueOrDefault(0) > 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, |