Bug 1073350: Validate that returned decoded Shmems have enough data r=cpearce a=abillings
authorRandell Jesup <rjesup@jesup.org>
Wed, 01 Oct 2014 22:13:18 -0400
changeset 216912 ff91afbb6355
parent 216911 07582278fef2
child 216913 16aa4dfa9001
push id3963
push userrjesup@wgate.com
push date2014-10-02 14:00 +0000
treeherdermozilla-beta@ff91afbb6355 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce, abillings
bugs1073350
milestone33.0
Bug 1073350: Validate that returned decoded Shmems have enough data r=cpearce a=abillings
content/media/gmp/GMPVideoDecoderParent.cpp
content/media/gmp/GMPVideoi420FrameImpl.cpp
content/media/gmp/GMPVideoi420FrameImpl.h
--- a/content/media/gmp/GMPVideoDecoderParent.cpp
+++ b/content/media/gmp/GMPVideoDecoderParent.cpp
@@ -231,16 +231,20 @@ GMPVideoDecoderParent::ActorDestroy(Acto
 
 bool
 GMPVideoDecoderParent::RecvDecoded(const GMPVideoi420FrameData& aDecodedFrame)
 {
   if (!mCallback) {
     return false;
   }
 
+  if (!GMPVideoi420FrameImpl::CheckFrameData(aDecodedFrame)) {
+    LOG(PR_LOG_ERROR, ("%s: Decoded frame corrupt, ignoring", __FUNCTION__));
+    return false;
+  }
   auto f = new GMPVideoi420FrameImpl(aDecodedFrame, &mVideoHost);
 
   // Ignore any return code. It is OK for this to fail without killing the process.
   mCallback->Decoded(f);
 
   return true;
 }
 
--- a/content/media/gmp/GMPVideoi420FrameImpl.cpp
+++ b/content/media/gmp/GMPVideoi420FrameImpl.cpp
@@ -58,16 +58,41 @@ GMPVideoi420FrameImpl::GetFrameFormat()
 }
 
 void
 GMPVideoi420FrameImpl::Destroy()
 {
   delete this;
 }
 
+/* static */ bool
+GMPVideoi420FrameImpl::CheckFrameData(const GMPVideoi420FrameData& aFrameData)
+{
+  // We may be passed the "wrong" shmem (one smaller than the actual size).
+  // This implies a bug or serious error on the child size.  Ignore this frame if so.
+  // Note: Size() greater than expected is also an error, but with no negative consequences
+  int32_t half_width = (aFrameData.mWidth() + 1) / 2;
+  if ((aFrameData.mYPlane().mStride() <= 0) || (aFrameData.mYPlane().mSize() <= 0) ||
+      (aFrameData.mUPlane().mStride() <= 0) || (aFrameData.mUPlane().mSize() <= 0) ||
+      (aFrameData.mVPlane().mStride() <= 0) || (aFrameData.mVPlane().mSize() <= 0) ||
+      (aFrameData.mYPlane().mSize() > (int32_t) aFrameData.mYPlane().mBuffer().Size<uint8_t>()) ||
+      (aFrameData.mUPlane().mSize() > (int32_t) aFrameData.mUPlane().mBuffer().Size<uint8_t>()) ||
+      (aFrameData.mVPlane().mSize() > (int32_t) aFrameData.mVPlane().mBuffer().Size<uint8_t>()) ||
+      (aFrameData.mYPlane().mStride() < aFrameData.mWidth()) ||
+      (aFrameData.mUPlane().mStride() < half_width) ||
+      (aFrameData.mVPlane().mStride() < half_width) ||
+      (aFrameData.mYPlane().mSize() < aFrameData.mYPlane().mStride() * aFrameData.mHeight()) ||
+      (aFrameData.mUPlane().mSize() < aFrameData.mUPlane().mStride() * ((aFrameData.mHeight()+1)/2)) ||
+      (aFrameData.mVPlane().mSize() < aFrameData.mVPlane().mStride() * ((aFrameData.mHeight()+1)/2)))
+  {
+    return false;
+  }
+  return true;
+}
+
 bool
 GMPVideoi420FrameImpl::CheckDimensions(int32_t aWidth, int32_t aHeight,
                                        int32_t aStride_y, int32_t aStride_u, int32_t aStride_v)
 {
   int32_t half_width = (aWidth + 1) / 2;
   if (aWidth < 1 || aHeight < 1 || aStride_y < aWidth ||
                                    aStride_u < half_width ||
                                    aStride_v < half_width) {
--- a/content/media/gmp/GMPVideoi420FrameImpl.h
+++ b/content/media/gmp/GMPVideoi420FrameImpl.h
@@ -18,16 +18,18 @@ class GMPVideoi420FrameData;
 class GMPVideoi420FrameImpl : public GMPVideoi420Frame
 {
   friend struct IPC::ParamTraits<mozilla::gmp::GMPVideoi420FrameImpl>;
 public:
   GMPVideoi420FrameImpl(GMPVideoHostImpl* aHost);
   GMPVideoi420FrameImpl(const GMPVideoi420FrameData& aFrameData, GMPVideoHostImpl* aHost);
   virtual ~GMPVideoi420FrameImpl();
 
+  static bool CheckFrameData(const GMPVideoi420FrameData& aFrameData);
+
   bool InitFrameData(GMPVideoi420FrameData& aFrameData);
   const GMPPlaneImpl* GetPlane(GMPPlaneType aType) const;
   GMPPlaneImpl* GetPlane(GMPPlaneType aType);
 
   // GMPVideoFrame
   virtual GMPVideoFrameFormat GetFrameFormat() MOZ_OVERRIDE;
   virtual void Destroy() MOZ_OVERRIDE;