diff --git a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc index 27a524fad9f6f..8fba8e03b327d 100644 --- a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc +++ b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc @@ -261,6 +261,18 @@ bool VP9VaapiVideoEncoderDelegate::Initialize( return false; } for (const auto& spatial_layer : config.spatial_layers) { + // vaCreateContext() and the VAEncCodedBuffer are sized from + // |coded_size_| (derived from |input_visible_size|); a spatial layer + // larger than that would cause the VA-API driver to encode past the + // context/coded-buffer bounds. This is also enforced at the Mojo + // boundary in MojoVideoEncodeAcceleratorService::Initialize(). + if (spatial_layer.width > coded_size_.width() || + spatial_layer.height > coded_size_.height()) { + VLOGF(1) << "Spatial layer " << spatial_layer.width << "x" + << spatial_layer.height << " exceeds coded size " + << coded_size_.ToString(); + return false; + } spatial_layer_resolutions.emplace_back( gfx::Size(spatial_layer.width, spatial_layer.height)); } diff --git a/media/mojo/services/mojo_video_encode_accelerator_service.cc b/media/mojo/services/mojo_video_encode_accelerator_service.cc index 3d603e63940be..fcfc92de5d2d8 100644 --- a/media/mojo/services/mojo_video_encode_accelerator_service.cc +++ b/media/mojo/services/mojo_video_encode_accelerator_service.cc @@ -18,6 +18,7 @@ #include "media/base/media_util.h" #include "media/mojo/mojom/video_encoder_info.mojom.h" #include "media/mojo/services/mojo_media_log.h" +#include "mojo/public/cpp/bindings/message.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "mojo/public/cpp/system/platform_handle.h" #include "third_party/perfetto/include/perfetto/tracing/track.h" @@ -147,6 +148,19 @@ void MojoVideoEncodeAcceleratorService::Initialize( .Run({EncoderStatus::Codes::kEncoderInitializationError}); return; } + // Spatial layers larger than |input_visible_size| are never produced by + // a well-behaved renderer and cause hardware encoders to size their VA + // context / coded buffer from |input_visible_size| while encoding at the + // (larger) spatial-layer size, which is a driver-heap OOB write. + if (spatial_layer.width > config.input_visible_size.width() || + spatial_layer.height > config.input_visible_size.height()) { + mojo::ReportBadMessage( + "VideoEncodeAccelerator.Initialize: spatial_layer larger than " + "input_visible_size"); + std::move(success_callback) + .Run({EncoderStatus::Codes::kEncoderInitializationError}); + return; + } } encoder_.reset();