Bug 1128939 - Part 1: Ensure we have any space in the media buffer before writing. r=k17e, a=abillings
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 11 Feb 2015 17:40:13 +1100
changeset 243762 783f63db37da
parent 243761 6d2cd80ee4e9
child 243763 78815ed2e606
push id4466
push userryanvm@gmail.com
push date2015-02-11 22:00 +0000
treeherdermozilla-beta@78815ed2e606 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersk17e, abillings
bugs1128939
milestone36.0
Bug 1128939 - Part 1: Ensure we have any space in the media buffer before writing. r=k17e, a=abillings
media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
--- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
@@ -162,16 +162,19 @@ private:
     };
     Vector<AuxRange> mDeferredSaiz;
     Vector<AuxRange> mDeferredSaio;
 
     MPEG4Source(const MPEG4Source &);
     MPEG4Source &operator=(const MPEG4Source &);
 
     bool ensureSrcBufferAllocated(int32_t size);
+    // Ensure that we have enough data in mMediaBuffer to copy our data.
+    // Returns false if not and clear mMediaBuffer.
+    bool ensureMediaBufferAllocated(int32_t size);
 };
 
 // This custom data source wraps an existing one and satisfies requests
 // falling entirely within a cached range from the cache while forwarding
 // all remaining requests to the wrapped datasource.
 // This is used to cache the full sampletable metadata for a single track,
 // possibly wrapping multiple times to cover all tracks, i.e.
 // Each MPEG4DataSource caches the sampletable metadata for a single track.
@@ -3265,22 +3268,35 @@ status_t MPEG4Source::lookForMoof() {
     }
 }
 
 bool MPEG4Source::ensureSrcBufferAllocated(int32_t aSize) {
     if (mSrcBackend.Length() >= aSize) {
         return true;
     }
     if (!mSrcBackend.SetLength(aSize)) {
+        ALOGE("Error insufficient memory, requested %u bytes (had:%u)",
+              aSize, mSrcBackend.Length());
         return false;
     }
     mSrcBuffer = mSrcBackend.Elements();
     return true;
 }
 
+bool MPEG4Source::ensureMediaBufferAllocated(int32_t aSize) {
+  if (mBuffer->size() < aSize) {
+      ALOGE("Error insufficient memory, requested %u bytes (had:%u)",
+            aSize, mBuffer->size());
+      mBuffer->release();
+      mBuffer = NULL;
+      return false;
+  }
+  return true;
+}
+
 status_t MPEG4Source::read(
         MediaBuffer **out, const ReadOptions *options) {
     Mutex::Autolock autoLock(mLock);
 
     CHECK(mStarted);
 
     if (!mLookedForMoof) {
         mLookedForMoof = lookForMoof() == OK;
@@ -3405,16 +3421,19 @@ status_t MPEG4Source::read(
           return ERROR_MALFORMED;
         }
         mBuffer = new MediaBuffer(max_size);
         assert(mBuffer);
     }
 
     if (!mIsAVC || mWantsNALFragments) {
         if (newBuffer) {
+            if (!ensureMediaBufferAllocated(size)) {
+                return ERROR_MALFORMED;
+            }
             ssize_t num_bytes_read =
                 mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
 
             if (num_bytes_read < (ssize_t)size) {
                 mBuffer->release();
                 mBuffer = NULL;
 
                 return ERROR_IO;
@@ -3512,16 +3531,19 @@ status_t MPEG4Source::read(
         return OK;
     } else {
         // Whole NAL units are returned but each fragment is prefixed by
         // the NAL length, stored in four bytes.
         ssize_t num_bytes_read = 0;
         int32_t drm = 0;
         bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
         if (usesDRM) {
+            if (!ensureMediaBufferAllocated(size)) {
+                return ERROR_MALFORMED;
+            }
             num_bytes_read =
                 mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
         } else {
             if (!ensureSrcBufferAllocated(size)) {
                 return ERROR_MALFORMED;
             }
             num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
         }
@@ -3557,17 +3579,19 @@ status_t MPEG4Source::read(
                     mBuffer = NULL;
                     return ERROR_MALFORMED;
                 }
 
                 if (nalLength == 0) {
                     continue;
                 }
 
-                CHECK(dstOffset + 4 <= mBuffer->size());
+                if (!ensureMediaBufferAllocated(dstOffset + 4 + nalLength)) {
+                    return ERROR_MALFORMED;
+                }
                 dstData[dstOffset++] = (uint8_t) (nalLength >> 24);
                 dstData[dstOffset++] = (uint8_t) (nalLength >> 16);
                 dstData[dstOffset++] = (uint8_t) (nalLength >> 8);
                 dstData[dstOffset++] = (uint8_t) nalLength;
                 memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
                 srcOffset += nalLength;
                 dstOffset += nalLength;
             }
@@ -3782,16 +3806,19 @@ status_t MPEG4Source::fragmentedRead(
         bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
         bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
         bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
         bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
     }
 
     if (!mIsAVC || mWantsNALFragments) {
         if (newBuffer) {
+            if (!ensureMediaBufferAllocated(size)) {
+                return ERROR_MALFORMED;
+            }
             ssize_t num_bytes_read =
                 mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
 
             if (num_bytes_read < (ssize_t)size) {
                 mBuffer->release();
                 mBuffer = NULL;
 
                 ALOGV("i/o error");
@@ -3867,16 +3894,19 @@ status_t MPEG4Source::fragmentedRead(
     } else {
         ALOGV("whole NAL");
         // Whole NAL units are returned but each fragment is prefixed by
         // the NAL unit's length, stored in four bytes.
         ssize_t num_bytes_read = 0;
         int32_t drm = 0;
         bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
         if (usesDRM) {
+            if (!ensureMediaBufferAllocated(size)) {
+                return ERROR_MALFORMED;
+            }
             num_bytes_read =
                 mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
         } else {
             if (!ensureSrcBufferAllocated(size)) {
                 return ERROR_MALFORMED;
             }
             num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
         }
@@ -3913,17 +3943,19 @@ status_t MPEG4Source::fragmentedRead(
                     mBuffer = NULL;
                     return ERROR_MALFORMED;
                 }
 
                 if (nalLength == 0) {
                     continue;
                 }
 
-                CHECK(dstOffset + 4 <= mBuffer->size());
+                if (!ensureMediaBufferAllocated(dstOffset + 4 + nalLength)) {
+                    return ERROR_MALFORMED;
+                }
                 dstData[dstOffset++] = (uint8_t) (nalLength >> 24);
                 dstData[dstOffset++] = (uint8_t) (nalLength >> 16);
                 dstData[dstOffset++] = (uint8_t) (nalLength >> 8);
                 dstData[dstOffset++] = (uint8_t) nalLength;
                 memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
                 srcOffset += nalLength;
                 dstOffset += nalLength;
             }