diff --git a/gfx/layers/ImageDataSerializer.cpp b/gfx/layers/ImageDataSerializer.cpp index 4cdd7099c156..bdcdb52297b9 100644 --- a/gfx/layers/ImageDataSerializer.cpp +++ b/gfx/layers/ImageDataSerializer.cpp @@ -78,6 +78,41 @@ ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, int32_t aYStride, 2 * GetAlignedStride<4>(aCbCrSize.height, aCbCrStride); } +uint32_t +ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, int32_t aYStride, + const gfx::IntSize& aCbCrSize, int32_t aCbCrStride, + uint32_t aYOffset, uint32_t aCbOffset, + uint32_t aCrOffset) +{ + MOZ_ASSERT(aYSize.height >= 0 && aYSize.width >= 0); + + if (aYSize.height < 0 || aYSize.width < 0 || aCbCrSize.height < 0 || aCbCrSize.width < 0 || + !gfx::Factory::AllowedSurfaceSize(IntSize(aYStride, aYSize.height)) || + !gfx::Factory::AllowedSurfaceSize(IntSize(aCbCrStride, aCbCrSize.height))) { + return 0; + } + + uint32_t yLength = GetAlignedStride<4>(aYStride, aYSize.height); + uint32_t cbCrLength = GetAlignedStride<4>(aCbCrStride, aCbCrSize.height); + if (yLength == 0 || cbCrLength == 0) { + return 0; + } + + CheckedInt yEnd = aYOffset; + yEnd += yLength; + CheckedInt cbEnd = aCbOffset; + cbEnd += cbCrLength; + CheckedInt crEnd = aCrOffset; + crEnd += cbCrLength; + + if (!yEnd.isValid() || !cbEnd.isValid() || !crEnd.isValid() || + yEnd.value() > aCbOffset || cbEnd.value() > aCrOffset) { + return 0; + } + + return crEnd.value(); +} + uint32_t ComputeYCbCrBufferSize(uint32_t aBufferSize) { diff --git a/gfx/layers/ImageDataSerializer.h b/gfx/layers/ImageDataSerializer.h index d48289effba2..b5ebe61ad97f 100644 --- a/gfx/layers/ImageDataSerializer.h +++ b/gfx/layers/ImageDataSerializer.h @@ -44,6 +44,13 @@ uint32_t ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, int32_t aYStride, const gfx::IntSize& aCbCrSize, int32_t aCbCrStride); +uint32_t ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, + int32_t aYStride, + const gfx::IntSize& aCbCrSize, + int32_t aCbCrStride, + uint32_t aYOffset, + uint32_t aCbOffset, + uint32_t aCrOffset); uint32_t ComputeYCbCrBufferSize(uint32_t aBufferSize); void ComputeYCbCrOffsets(int32_t yStride, int32_t yHeight, diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index 20e0f7913d99..0b2a1528848c 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -292,7 +292,9 @@ CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc, const YCbCrDescriptor& ycbcr = desc.get_YCbCrDescriptor(); reqSize = ImageDataSerializer::ComputeYCbCrBufferSize(ycbcr.ySize(), ycbcr.yStride(), - ycbcr.cbCrSize(), ycbcr.cbCrStride()); + ycbcr.cbCrSize(), ycbcr.cbCrStride(), + ycbcr.yOffset(), ycbcr.cbOffset(), + ycbcr.crOffset()); break; } case BufferDescriptor::TRGBDescriptor: { @@ -305,7 +307,7 @@ CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc, MOZ_CRASH("GFX: Bad descriptor"); } - if (bufSize < reqSize) { + if (reqSize == 0 || bufSize < reqSize) { NS_ERROR("A client process gave a shmem too small to fit for its descriptor!"); return nullptr; }