Bug 971695 - 2/2 - make YCbCrImageDataSerializer check data size - r=nical
authorBenoit Jacob <bjacob@mozilla.com>
Thu, 20 Feb 2014 16:04:13 -0500
changeset 170114 5149dd54f49a32bf1338ee28070c61a372b492a9
parent 170113 e05ca48e66211612ecaee440d33052e501f48fab
child 170115 4027d48cbc51efce06e2fe8a4675e3a4df27c707
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersnical
bugs971695
milestone30.0a1
Bug 971695 - 2/2 - make YCbCrImageDataSerializer check data size - r=nical
gfx/layers/YCbCrImageDataSerializer.cpp
gfx/layers/YCbCrImageDataSerializer.h
gfx/layers/basic/BasicCompositor.cpp
gfx/layers/client/TextureClient.cpp
gfx/layers/composite/TextureHost.cpp
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d9/TextureD3D9.cpp
gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
gfx/tests/gtest/TestTextures.cpp
--- a/gfx/layers/YCbCrImageDataSerializer.cpp
+++ b/gfx/layers/YCbCrImageDataSerializer.cpp
@@ -46,137 +46,159 @@ struct YCbCrBufferInfo
   uint32_t mYWidth;
   uint32_t mYHeight;
   uint32_t mCbCrStride;
   uint32_t mCbCrWidth;
   uint32_t mCbCrHeight;
   StereoMode mStereoMode;
 };
 
-static YCbCrBufferInfo* GetYCbCrBufferInfo(uint8_t* aData)
+static YCbCrBufferInfo* GetYCbCrBufferInfo(uint8_t* aData, size_t aDataSize)
 {
-  return reinterpret_cast<YCbCrBufferInfo*>(aData);
+  return aDataSize >= sizeof(YCbCrBufferInfo)
+         ? reinterpret_cast<YCbCrBufferInfo*>(aData)
+         : nullptr;
 }
 
-bool YCbCrImageDataDeserializerBase::IsValid()
+void YCbCrImageDataDeserializerBase::Validate()
 {
-  if (mData == nullptr) {
-    return false;
+  mIsValid = false;
+  if (!mData) {
+    return;
+  }
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
+  if (!info) {
+    return;
   }
-  return true;
+  size_t requiredSize = ComputeMinBufferSize(
+                          IntSize(info->mYWidth, info->mYHeight),
+                          info->mYStride,
+                          IntSize(info->mCbCrWidth, info->mCbCrHeight),
+                          info->mCbCrStride);
+  mIsValid = requiredSize <= mDataSize;
+
 }
 
 uint8_t* YCbCrImageDataDeserializerBase::GetYData()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
   return reinterpret_cast<uint8_t*>(info) + info->mYOffset;
 }
 
 uint8_t* YCbCrImageDataDeserializerBase::GetCbData()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
   return reinterpret_cast<uint8_t*>(info) + info->mCbOffset;
 }
 
 uint8_t* YCbCrImageDataDeserializerBase::GetCrData()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
   return reinterpret_cast<uint8_t*>(info) + info->mCrOffset;
 }
 
 uint8_t* YCbCrImageDataDeserializerBase::GetData()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
   return (reinterpret_cast<uint8_t*>(info)) + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
 }
 
 uint32_t YCbCrImageDataDeserializerBase::GetYStride()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
   return info->mYStride;
 }
 
 uint32_t YCbCrImageDataDeserializerBase::GetCbCrStride()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
   return info->mCbCrStride;
 }
 
 gfx::IntSize YCbCrImageDataDeserializerBase::GetYSize()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
   return gfx::IntSize(info->mYWidth, info->mYHeight);
 }
 
 gfx::IntSize YCbCrImageDataDeserializerBase::GetCbCrSize()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
   return gfx::IntSize(info->mCbCrWidth, info->mCbCrHeight);
 }
 
 StereoMode YCbCrImageDataDeserializerBase::GetStereoMode()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
   return info->mStereoMode;
 }
 
 // Offset in bytes
 static size_t ComputeOffset(uint32_t aHeight, uint32_t aStride)
 {
   return MOZ_ALIGN_WORD(aHeight * aStride);
 }
 
 // Minimum required shmem size in bytes
 size_t
-YCbCrImageDataSerializer::ComputeMinBufferSize(const gfx::IntSize& aYSize,
-                                               const gfx::IntSize& aCbCrSize)
+YCbCrImageDataDeserializerBase::ComputeMinBufferSize(const gfx::IntSize& aYSize,
+                                                   uint32_t aYStride,
+                                                   const gfx::IntSize& aCbCrSize,
+                                                   uint32_t aCbCrStride)
 {
-  uint32_t yStride = aYSize.width;
-  uint32_t CbCrStride = aCbCrSize.width;
+  return ComputeOffset(aYSize.height, aYStride)
+         + 2 * ComputeOffset(aCbCrSize.height, aCbCrStride)
+         + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
+}
 
-  return ComputeOffset(aYSize.height, yStride)
-         + 2 * ComputeOffset(aCbCrSize.height, CbCrStride)
-         + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
+// Minimum required shmem size in bytes
+size_t
+YCbCrImageDataDeserializerBase::ComputeMinBufferSize(const gfx::IntSize& aYSize,
+                                                   const gfx::IntSize& aCbCrSize)
+{
+  return ComputeMinBufferSize(aYSize, aYSize.width, aCbCrSize, aCbCrSize.width);
 }
 
 // Offset in bytes
 static size_t ComputeOffset(uint32_t aSize)
 {
   return MOZ_ALIGN_WORD(aSize);
 }
 
 // Minimum required shmem size in bytes
 size_t
-YCbCrImageDataSerializer::ComputeMinBufferSize(uint32_t aSize)
+YCbCrImageDataDeserializerBase::ComputeMinBufferSize(uint32_t aSize)
 {
   return ComputeOffset(aSize) + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
 }
 
 void
 YCbCrImageDataSerializer::InitializeBufferInfo(uint32_t aYOffset,
                                                uint32_t aCbOffset,
                                                uint32_t aCrOffset,
                                                uint32_t aYStride,
                                                uint32_t aCbCrStride,
                                                const gfx::IntSize& aYSize,
                                                const gfx::IntSize& aCbCrSize,
                                                StereoMode aStereoMode)
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
+  MOZ_ASSERT(info); // OK to assert here, this method is client-side-only
   uint32_t info_size = MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
   info->mYOffset = info_size + aYOffset;
   info->mCbOffset = info_size + aCbOffset;
   info->mCrOffset = info_size + aCrOffset;
   info->mYStride = aYStride;
   info->mYWidth = aYSize.width;
   info->mYHeight = aYSize.height;
   info->mCbCrStride = aCbCrStride;
   info->mCbCrWidth = aCbCrSize.width;
   info->mCbCrHeight = aCbCrSize.height;
   info->mStereoMode = aStereoMode;
+  Validate();
 }
 
 void
 YCbCrImageDataSerializer::InitializeBufferInfo(uint32_t aYStride,
                                                uint32_t aCbCrStride,
                                                const gfx::IntSize& aYSize,
                                                const gfx::IntSize& aCbCrSize,
                                                StereoMode aStereoMode)
--- a/gfx/layers/YCbCrImageDataSerializer.h
+++ b/gfx/layers/YCbCrImageDataSerializer.h
@@ -25,17 +25,17 @@ class Image;
 /**
  * Convenience class to share code between YCbCrImageDataSerializer
  * and YCbCrImageDataDeserializer.
  * Do not use it.
  */
 class YCbCrImageDataDeserializerBase
 {
 public:
-  bool IsValid();
+  bool IsValid() const { return mIsValid; }
 
   /**
    * Returns the Y channel data pointer.
    */
   uint8_t* GetYData();
   /**
    * Returns the Cb channel data pointer.
    */
@@ -68,21 +68,42 @@ public:
    * Stereo mode for the image.
    */
   StereoMode GetStereoMode();
 
   /**
    * Return a pointer to the begining of the data buffer.
    */
   uint8_t* GetData();
+
+  /**
+   * This function is meant as a helper to know how much shared memory we need
+   * to allocate in a shmem in order to place a shared YCbCr image blob of
+   * given dimensions.
+   */
+  static size_t ComputeMinBufferSize(const gfx::IntSize& aYSize,
+                                     uint32_t aYStride,
+                                     const gfx::IntSize& aCbCrSize,
+                                     uint32_t aCbCrStride);
+  static size_t ComputeMinBufferSize(const gfx::IntSize& aYSize,
+                                     const gfx::IntSize& aCbCrSize);
+  static size_t ComputeMinBufferSize(uint32_t aSize);
+
 protected:
-  YCbCrImageDataDeserializerBase(uint8_t* aData)
-  : mData (aData) {}
+  YCbCrImageDataDeserializerBase(uint8_t* aData, size_t aDataSize)
+    : mData (aData)
+    , mDataSize(aDataSize)
+    , mIsValid(false)
+  {}
+
+  void Validate();
 
   uint8_t* mData;
+  size_t mDataSize;
+  bool mIsValid;
 };
 
 /**
  * A view on a YCbCr image stored with its metadata in a blob of memory.
  * It is only meant as a convenience to access the image data, and does not own
  * the data. The instance can live on the stack and used as follows:
  *
  * const YCbCrImage& yuv = sharedImage.get_YCbCrImage();
@@ -90,26 +111,22 @@ protected:
  * if (!deserializer.IsValid()) {
  *   // handle error
  * }
  * size = deserializer.GetYSize(); // work with the data, etc...
  */
 class MOZ_STACK_CLASS YCbCrImageDataSerializer : public YCbCrImageDataDeserializerBase
 {
 public:
-  YCbCrImageDataSerializer(uint8_t* aData) : YCbCrImageDataDeserializerBase(aData) {}
-
-  /**
-   * This function is meant as a helper to know how much shared memory we need
-   * to allocate in a shmem in order to place a shared YCbCr image blob of
-   * given dimensions.
-   */
-  static size_t ComputeMinBufferSize(const gfx::IntSize& aYSize,
-                                     const gfx::IntSize& aCbCrSize);
-  static size_t ComputeMinBufferSize(uint32_t aSize);
+  YCbCrImageDataSerializer(uint8_t* aData, size_t aDataSize)
+    : YCbCrImageDataDeserializerBase(aData, aDataSize)
+  {
+    // a serializer needs to be usable before correct buffer info has been written to it
+    mIsValid = !!mData;
+  }
 
   /**
    * Write the image informations in the buffer for given dimensions.
    * The provided pointer should point to the beginning of the (chunk of)
    * buffer on which we want to store the image.
    */
   void InitializeBufferInfo(uint32_t aYOffset,
                             uint32_t aCbOffset,
@@ -144,17 +161,21 @@ public:
  * if (!deserializer.IsValid()) {
  *   // handle error
  * }
  * size = deserializer.GetYSize(); // work with the data, etc...
  */
 class MOZ_STACK_CLASS YCbCrImageDataDeserializer : public YCbCrImageDataDeserializerBase
 {
 public:
-  YCbCrImageDataDeserializer(uint8_t* aData) : YCbCrImageDataDeserializerBase(aData) {}
+  YCbCrImageDataDeserializer(uint8_t* aData, size_t aDataSize)
+    : YCbCrImageDataDeserializerBase(aData, aDataSize)
+  {
+    Validate();
+  }
 
   /**
    * Convert the YCbCr data into RGB and return a DataSourceSurface.
    * This is a costly operation, so use it only when YCbCr compositing is
    * not supported.
    */
   TemporaryRef<gfx::DataSourceSurface> ToDataSourceSurface();
 };
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -175,17 +175,18 @@ public:
     if (!mBuffer) {
       return false;
     }
     return ConvertImageToRGB(*mBuffer);
   }
 
   bool ConvertImageToRGB(const SurfaceDescriptor& aImage)
   {
-    YCbCrImageDataDeserializer deserializer(aImage.get_YCbCrImage().data().get<uint8_t>());
+    YCbCrImageDataDeserializer deserializer(aImage.get_YCbCrImage().data().get<uint8_t>(),
+                                            aImage.get_YCbCrImage().data().Size<uint8_t>());
     PlanarYCbCrData data;
     DeserializerToPlanarYCbCrImageData(deserializer, data);
 
     gfx::SurfaceFormat format = SurfaceFormat::B8G8R8X8;
     gfx::IntSize size;
     gfx::GetYCbCrToRGBDestFormatAndSize(data, format, size);
     if (size.width > PlanarYCbCrImage::MAX_DIMENSION ||
         size.height > PlanarYCbCrImage::MAX_DIMENSION) {
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -612,17 +612,17 @@ BufferTextureClient::Unlock()
 bool
 BufferTextureClient::UpdateYCbCr(const PlanarYCbCrData& aData)
 {
   MOZ_ASSERT(mFormat == gfx::SurfaceFormat::YUV, "This textureClient can only use YCbCr data");
   MOZ_ASSERT(!IsImmutable());
   MOZ_ASSERT(IsValid());
   MOZ_ASSERT(aData.mCbSkip == aData.mCrSkip);
 
-  YCbCrImageDataSerializer serializer(GetBuffer());
+  YCbCrImageDataSerializer serializer(GetBuffer(), GetBufferSize());
   MOZ_ASSERT(serializer.IsValid());
   if (!serializer.CopyData(aData.mYChannel, aData.mCbChannel, aData.mCrChannel,
                            aData.mYSize, aData.mYStride,
                            aData.mCbCrSize, aData.mCbCrStride,
                            aData.mYSkip, aData.mCbSkip)) {
     NS_WARNING("Failed to copy image data!");
     return false;
   }
@@ -642,17 +642,17 @@ BufferTextureClient::AllocateForYCbCr(gf
 {
   MOZ_ASSERT(IsValid());
 
   size_t bufSize = YCbCrImageDataSerializer::ComputeMinBufferSize(aYSize,
                                                                   aCbCrSize);
   if (!Allocate(bufSize)) {
     return false;
   }
-  YCbCrImageDataSerializer serializer(GetBuffer());
+  YCbCrImageDataSerializer serializer(GetBuffer(), GetBufferSize());
   serializer.InitializeBufferInfo(aYSize,
                                   aCbCrSize,
                                   aStereoMode);
   mSize = aYSize;
   return true;
 }
 
 
@@ -965,17 +965,17 @@ AutoLockYCbCrClient::Update(PlanarYCbCrI
   }
 
   if (!EnsureDeprecatedTextureClient(aImage)) {
     return false;
   }
 
   ipc::Shmem& shmem = mDescriptor->get_YCbCrImage().data();
 
-  YCbCrImageDataSerializer serializer(shmem.get<uint8_t>());
+  YCbCrImageDataSerializer serializer(shmem.get<uint8_t>(), shmem.Size<uint8_t>());
   if (!serializer.CopyData(data->mYChannel, data->mCbChannel, data->mCrChannel,
                            data->mYSize, data->mYStride,
                            data->mCbCrSize, data->mCbCrStride,
                            data->mYSkip, data->mCbSkip)) {
     NS_WARNING("Failed to copy image data!");
     return false;
   }
   return true;
@@ -994,17 +994,17 @@ bool AutoLockYCbCrClient::EnsureDeprecat
     return false;
   }
 
   bool needsAllocation = false;
   if (mDescriptor->type() != SurfaceDescriptor::TYCbCrImage) {
     needsAllocation = true;
   } else {
     ipc::Shmem& shmem = mDescriptor->get_YCbCrImage().data();
-    YCbCrImageDataSerializer serializer(shmem.get<uint8_t>());
+    YCbCrImageDataSerializer serializer(shmem.get<uint8_t>(), shmem.Size<uint8_t>());
     if (serializer.GetYSize() != data->mYSize ||
         serializer.GetCbCrSize() != data->mCbCrSize) {
       needsAllocation = true;
     }
   }
 
   if (!needsAllocation) {
     return true;
@@ -1015,17 +1015,17 @@ bool AutoLockYCbCrClient::EnsureDeprecat
   ipc::SharedMemory::SharedMemoryType shmType = OptimalShmemType();
   size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(data->mYSize,
                                                                data->mCbCrSize);
   ipc::Shmem shmem;
   if (!mDeprecatedTextureClient->GetForwarder()->AllocUnsafeShmem(size, shmType, &shmem)) {
     return false;
   }
 
-  YCbCrImageDataSerializer serializer(shmem.get<uint8_t>());
+  YCbCrImageDataSerializer serializer(shmem.get<uint8_t>(), shmem.Size<uint8_t>());
   serializer.InitializeBufferInfo(data->mYSize,
                                   data->mCbCrSize,
                                   data->mStereoMode);
 
   *mDescriptor = YCbCrImage(shmem, 0);
 
   return true;
 }
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -489,17 +489,17 @@ BufferTextureHost::Upload(nsIntRegion *a
     // earlier. It is conceivable that on certain rare conditions with async-video
     // we may end up here for the first frame, but this should not happen repeatedly.
     return false;
   }
   if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
     NS_WARNING("BufferTextureHost: unsupported format!");
     return false;
   } else if (mFormat == gfx::SurfaceFormat::YUV) {
-    YCbCrImageDataDeserializer yuvDeserializer(GetBuffer());
+    YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize());
     MOZ_ASSERT(yuvDeserializer.IsValid());
 
     if (!mCompositor->SupportsEffect(EFFECT_YCBCR)) {
       RefPtr<gfx::DataSourceSurface> surf = yuvDeserializer.ToDataSourceSurface();
       if (!mFirstSource) {
         mFirstSource = mCompositor->CreateDataTextureSource(mFlags);
       }
       mFirstSource->Update(surf, aRegion);
@@ -580,17 +580,17 @@ BufferTextureHost::Upload(nsIntRegion *a
 TemporaryRef<gfx::DataSourceSurface>
 BufferTextureHost::GetAsSurface()
 {
   RefPtr<gfx::DataSourceSurface> result;
   if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
     NS_WARNING("BufferTextureHost: unsupported format!");
     return nullptr;
   } else if (mFormat == gfx::SurfaceFormat::YUV) {
-    YCbCrImageDataDeserializer yuvDeserializer(GetBuffer());
+    YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize());
     if (!yuvDeserializer.IsValid()) {
       return nullptr;
     }
     result = yuvDeserializer.ToDataSourceSurface();
   } else {
     ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize());
     if (!deserializer.IsValid()) {
       NS_ERROR("Failed to deserialize image!");
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -891,17 +891,18 @@ DeprecatedTextureHostYCbCrD3D11::SetComp
 
 void
 DeprecatedTextureHostYCbCrD3D11::UpdateImpl(const SurfaceDescriptor& aImage,
                                   nsIntRegion* aRegion,
                                   nsIntPoint* aOffset)
 {
   MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TYCbCrImage);
 
-  YCbCrImageDataDeserializer yuvDeserializer(aImage.get_YCbCrImage().data().get<uint8_t>());
+  YCbCrImageDataDeserializer yuvDeserializer(aImage.get_YCbCrImage().data().get<uint8_t>(),
+                                             aImage.get_YCbCrImage().data().Size<uint8_t>());
 
   gfx::IntSize gfxCbCrSize = yuvDeserializer.GetCbCrSize();
 
   gfx::IntSize size = yuvDeserializer.GetYSize();
 
   RefPtr<DataTextureSource> srcY;
   RefPtr<DataTextureSource> srcCb;
   RefPtr<DataTextureSource> srcCr;
--- a/gfx/layers/d3d9/TextureD3D9.cpp
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -437,17 +437,18 @@ DeprecatedTextureHostYCbCrD3D9::UpdateIm
                                  nsIntPoint *aOffset)
 {
   MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TYCbCrImage);
 
   if (!mCompositor->device()) {
     return;
   }
 
-  YCbCrImageDataDeserializer yuvDeserializer(aImage.get_YCbCrImage().data().get<uint8_t>());
+  YCbCrImageDataDeserializer yuvDeserializer(aImage.get_YCbCrImage().data().get<uint8_t>(),
+                                             aImage.get_YCbCrImage().data().Size<uint8_t>());
 
   mSize = yuvDeserializer.GetYSize();
   IntSize cbCrSize = yuvDeserializer.GetCbCrSize();
   mStereoMode = yuvDeserializer.GetStereoMode();
 
   DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
   RefPtr<DataTextureSource> srcY;
   RefPtr<DataTextureSource> srcCb;
--- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
+++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
@@ -120,17 +120,17 @@ SharedPlanarYCbCrImage::SetData(const Pl
   }
   // do not set mBuffer like in PlanarYCbCrImage because the later
   // will try to manage this memory without knowing it belongs to a
   // shmem.
   mBufferSize = YCbCrImageDataSerializer::ComputeMinBufferSize(mData.mYSize,
                                                                mData.mCbCrSize);
   mSize = mData.mPicSize;
 
-  YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer());
+  YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer(), mTextureClient->GetBufferSize());
   mData.mYChannel = serializer.GetYData();
   mData.mCbChannel = serializer.GetCbData();
   mData.mCrChannel = serializer.GetCrData();
   mTextureClient->MarkImmutable();
 }
 
 // needs to be overriden because the parent class sets mBuffer which we
 // do not want to happen.
@@ -143,32 +143,32 @@ SharedPlanarYCbCrImage::AllocateAndGetNe
   // get new buffer _without_ setting mBuffer.
   if (!mTextureClient->Allocate(size)) {
     return nullptr;
   }
 
   // update buffer size
   mBufferSize = size;
 
-  YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer());
+  YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer(), mTextureClient->GetBufferSize());
   return serializer.GetData();
 }
 
 void
 SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
 {
   mData = aData;
   mSize = aData.mPicSize;
   /* SetDataNoCopy is used to update YUV plane offsets without (re)allocating
    * memory previously allocated with AllocateAndGetNewBuffer().
    * serializer.GetData() returns the address of the memory previously allocated
    * with AllocateAndGetNewBuffer(), that we subtract from the Y, Cb, Cr
    * channels to compute 0-based offsets to pass to InitializeBufferInfo.
    */
-  YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer());
+  YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer(), mTextureClient->GetBufferSize());
   uint8_t *base = serializer.GetData();
   uint32_t yOffset = aData.mYChannel - base;
   uint32_t cbOffset = aData.mCbChannel - base;
   uint32_t crOffset = aData.mCrChannel - base;
   serializer.InitializeBufferInfo(yOffset,
                                   cbOffset,
                                   crOffset,
                                   aData.mYStride,
@@ -202,17 +202,17 @@ SharedPlanarYCbCrImage::Allocate(PlanarY
 
   size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(aData.mYSize,
                                                                aData.mCbCrSize);
 
   if (AllocateBuffer(static_cast<uint32_t>(size)) == nullptr) {
     return false;
   }
 
-  YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer());
+  YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer(), mTextureClient->GetBufferSize());
   serializer.InitializeBufferInfo(aData.mYSize,
                                   aData.mCbCrSize,
                                   aData.mStereoMode);
   MOZ_ASSERT(serializer.IsValid());
 
   aData.mYChannel = serializer.GetYData();
   aData.mCbChannel = serializer.GetCbData();
   aData.mCrChannel = serializer.GetCrData();
@@ -253,17 +253,17 @@ DeprecatedSharedPlanarYCbCrImage::SetDat
 
   // do not set mBuffer like in PlanarYCbCrImage because the later
   // will try to manage this memory without knowing it belongs to a
   // shmem.
   mBufferSize = YCbCrImageDataSerializer::ComputeMinBufferSize(mData.mYSize,
                                                                mData.mCbCrSize);
   mSize = mData.mPicSize;
 
-  YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>());
+  YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>(), mShmem.Size<uint8_t>());
   MOZ_ASSERT(aData.mCbSkip == aData.mCrSkip);
   if (!serializer.CopyData(aData.mYChannel, aData.mCbChannel, aData.mCrChannel,
                            aData.mYSize, aData.mYStride,
                            aData.mCbCrSize, aData.mCbCrStride,
                            aData.mYSkip, aData.mCbSkip)) {
     NS_WARNING("Failed to copy image data!");
   }
   mData.mYChannel = serializer.GetYData();
@@ -282,26 +282,26 @@ DeprecatedSharedPlanarYCbCrImage::Alloca
   // get new buffer _without_ setting mBuffer.
   if (!AllocateBuffer(size)) {
     return nullptr;
   }
 
   // update buffer size
   mBufferSize = size;
 
-  YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>());
+  YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>(), mShmem.Size<uint8_t>());
   return serializer.GetData();
 }
 
 void
 DeprecatedSharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
 {
   mData = aData;
   mSize = aData.mPicSize;
-  YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>());
+  YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>(), mShmem.Size<uint8_t>());
   serializer.InitializeBufferInfo(aData.mYSize,
                                   aData.mCbCrSize,
                                   aData.mStereoMode);
 }
 
 uint8_t* 
 DeprecatedSharedPlanarYCbCrImage::AllocateBuffer(uint32_t aSize)
 {
@@ -322,17 +322,17 @@ DeprecatedSharedPlanarYCbCrImage::Alloca
 
   size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(aData.mYSize,
                                                                aData.mCbCrSize);
 
   if (AllocateBuffer(static_cast<uint32_t>(size)) == nullptr) {
     return false;
   }
 
-  YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>());
+  YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>(), mShmem.Size<uint8_t>());
   serializer.InitializeBufferInfo(aData.mYSize,
                                   aData.mCbCrSize,
                                   aData.mStereoMode);
   if (!serializer.IsValid() || mShmem.Size<uint8_t>() < size) {
     mSurfaceAllocator->DeallocShmem(mShmem);
     return false;
   }
 
--- a/gfx/tests/gtest/TestTextures.cpp
+++ b/gfx/tests/gtest/TestTextures.cpp
@@ -176,17 +176,17 @@ void TestTextureClientYCbCr(TextureClien
   ASSERT_EQ(host->GetFlags(), client->GetFlags());
 
   // host read
   ASSERT_TRUE(host->Lock());
 
   // This will work iff the compositor is not BasicCompositor
   ASSERT_EQ(host->GetFormat(), mozilla::gfx::SurfaceFormat::YUV);
 
-  YCbCrImageDataDeserializer yuvDeserializer(host->GetBuffer());
+  YCbCrImageDataDeserializer yuvDeserializer(host->GetBuffer(), host->GetBufferSize());
   ASSERT_TRUE(yuvDeserializer.IsValid());
   PlanarYCbCrData data;
   data.mYChannel = yuvDeserializer.GetYData();
   data.mCbChannel = yuvDeserializer.GetCbData();
   data.mCrChannel = yuvDeserializer.GetCrData();
   data.mYStride = yuvDeserializer.GetYStride();
   data.mCbCrStride = yuvDeserializer.GetCbCrStride();
   data.mStereoMode = yuvDeserializer.GetStereoMode();