Bug 1085175 - r=roc
☠☠ backed out by 1db845973613 ☠ ☠
authorMatthew Gregan <kinetik@flim.org>
Tue, 11 Nov 2014 08:58:52 +1300
changeset 214865 992ad9a82996555b404e14cc187cc60b766a4dd7
parent 214864 d54ee2df476366f462a70171ea3a43407e19d456
child 214866 dc2e15a7df8d327e2c359cf0bb4e899c9fc755a6
push id51587
push usermgregan@mozilla.com
push dateMon, 10 Nov 2014 20:25:31 +0000
treeherdermozilla-inbound@992ad9a82996 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1085175
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1085175 - r=roc
dom/media/MediaCache.cpp
media/libnestegg/include/nestegg-stdint.h
media/libnestegg/src/nestegg.c
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -1168,16 +1168,17 @@ MediaCache::Update()
 
       MediaCacheStream* stream = mStreams[i];
       if (stream->mClosed)
         continue;
 
       // Figure out where we should be reading from. It's the first
       // uncached byte after the current mStreamOffset.
       int64_t dataOffset = stream->GetCachedDataEndInternal(stream->mStreamOffset);
+      MOZ_ASSERT(dataOffset >= 0);
 
       // Compute where we'd actually seek to to read at readOffset
       int64_t desiredOffset = dataOffset;
       if (stream->mIsTransportSeekable) {
         if (desiredOffset > stream->mChannelOffset &&
             desiredOffset <= stream->mChannelOffset + SEEK_VS_READ_THRESHOLD) {
           // Assume it's more efficient to just keep reading up to the
           // desired position instead of trying to seek
@@ -1700,16 +1701,17 @@ MediaCacheStream::NotifyDataLength(int64
 void
 MediaCacheStream::NotifyDataStarted(int64_t aOffset)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
   NS_WARN_IF_FALSE(aOffset == mChannelOffset,
                    "Server is giving us unexpected offset");
+  MOZ_ASSERT(aOffset >= 0);
   mChannelOffset = aOffset;
   if (mStreamLength >= 0) {
     // If we started reading at a certain offset, then for sure
     // the stream is at least that long.
     mStreamLength = std::max(mStreamLength, mChannelOffset);
   }
 }
 
@@ -2129,33 +2131,38 @@ MediaCacheStream::Seek(int32_t aWhence, 
 {
   NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
 
   ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
   if (mClosed)
     return NS_ERROR_FAILURE;
 
   int64_t oldOffset = mStreamOffset;
+  int64_t newOffset = mStreamOffset;
   switch (aWhence) {
   case PR_SEEK_END:
     if (mStreamLength < 0)
       return NS_ERROR_FAILURE;
-    mStreamOffset = mStreamLength + aOffset;
+    newOffset = mStreamLength + aOffset;
     break;
   case PR_SEEK_CUR:
-    mStreamOffset += aOffset;
+    newOffset += aOffset;
     break;
   case PR_SEEK_SET:
-    mStreamOffset = aOffset;
+    newOffset = aOffset;
     break;
   default:
     NS_ERROR("Unknown whence");
     return NS_ERROR_FAILURE;
   }
 
+  if (newOffset < 0)
+    return NS_ERROR_FAILURE;
+  mStreamOffset = newOffset;
+
   CACHE_LOG(PR_LOG_DEBUG, ("Stream %p Seek to %lld", this, (long long)mStreamOffset));
   gMediaCache->NoteSeek(this, oldOffset);
 
   gMediaCache->QueueUpdate();
   return NS_OK;
 }
 
 int64_t
@@ -2187,21 +2194,20 @@ MediaCacheStream::Read(char* aBuffer, ui
     if (mStreamLength >= 0) {
       // Don't try to read beyond the end of the stream
       int64_t bytesRemaining = mStreamLength - mStreamOffset;
       if (bytesRemaining <= 0) {
         // Get out of here and return NS_OK
         break;
       }
       size = std::min(size, bytesRemaining);
-      // Clamp size until 64-bit file size issues (bug 500784) are fixed.
+      // Clamp size until 64-bit file size issues are fixed.
       size = std::min(size, int64_t(INT32_MAX));
     }
 
-    int32_t bytes;
     int32_t cacheBlock = streamBlock < mBlocks.Length() ? mBlocks[streamBlock] : -1;
     if (cacheBlock < 0) {
       // We don't have a complete cached block here.
 
       if (count > 0) {
         // Some data has been read, so return what we've got instead of
         // blocking or trying to find a stream with a partial block.
         break;
@@ -2219,17 +2225,20 @@ MediaCacheStream::Read(char* aBuffer, ui
           streamWithPartialBlock = stream;
           break;
         }
       }
       if (streamWithPartialBlock) {
         // We can just use the data in mPartialBlockBuffer. In fact we should
         // use it rather than waiting for the block to fill and land in
         // the cache.
-        bytes = std::min<int64_t>(size, streamWithPartialBlock->mChannelOffset - mStreamOffset);
+        int64_t bytes = std::min<int64_t>(size, streamWithPartialBlock->mChannelOffset - mStreamOffset);
+        // Clamp bytes until 64-bit file size issues are fixed.
+        bytes = std::min(bytes, int64_t(INT32_MAX));
+        NS_ABORT_IF_FALSE(bytes >= 0 && bytes <= aCount, "Bytes out of range.");
         memcpy(aBuffer,
           reinterpret_cast<char*>(streamWithPartialBlock->mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes);
         if (mCurrentMode == MODE_METADATA) {
           streamWithPartialBlock->mMetadataInPartialBlockBuffer = true;
         }
         mStreamOffset += bytes;
         count = bytes;
         break;
@@ -2243,16 +2252,17 @@ MediaCacheStream::Read(char* aBuffer, ui
         return NS_ERROR_FAILURE;
       }
       continue;
     }
 
     gMediaCache->NoteBlockUsage(this, cacheBlock, mCurrentMode, TimeStamp::Now());
 
     int64_t offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock;
+    int32_t bytes;
     NS_ABORT_IF_FALSE(size >= 0 && size <= INT32_MAX, "Size out of range.");
     nsresult rv = gMediaCache->ReadCacheFile(offset, aBuffer + count, int32_t(size), &bytes);
     if (NS_FAILED(rv)) {
       if (count == 0)
         return rv;
       // If we did successfully read some data, may as well return it
       break;
     }
@@ -2279,19 +2289,17 @@ MediaCacheStream::ReadAt(int64_t aOffset
 
   ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
   nsresult rv = Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
   if (NS_FAILED(rv)) return rv;
   return Read(aBuffer, aCount, aBytes);
 }
 
 nsresult
-MediaCacheStream::ReadFromCache(char* aBuffer,
-                                  int64_t aOffset,
-                                  int64_t aCount)
+MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, int64_t aCount)
 {
   ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
   if (mClosed)
     return NS_ERROR_FAILURE;
 
   // Read one block (or part of a block) at a time
   uint32_t count = 0;
   int64_t streamOffset = aOffset;
@@ -2303,28 +2311,31 @@ MediaCacheStream::ReadFromCache(char* aB
 
     if (mStreamLength >= 0) {
       // Don't try to read beyond the end of the stream
       int64_t bytesRemaining = mStreamLength - streamOffset;
       if (bytesRemaining <= 0) {
         return NS_ERROR_FAILURE;
       }
       size = std::min(size, bytesRemaining);
-      // Clamp size until 64-bit file size issues (bug 500784) are fixed.
+      // Clamp size until 64-bit file size issues are fixed.
       size = std::min(size, int64_t(INT32_MAX));
     }
 
     int32_t bytes;
     uint32_t channelBlock = uint32_t(mChannelOffset/BLOCK_SIZE);
     int32_t cacheBlock = streamBlock < mBlocks.Length() ? mBlocks[streamBlock] : -1;
     if (channelBlock == streamBlock && streamOffset < mChannelOffset) {
       // We can just use the data in mPartialBlockBuffer. In fact we should
       // use it rather than waiting for the block to fill and land in
       // the cache.
-      bytes = std::min<int64_t>(size, mChannelOffset - streamOffset);
+      // Clamp bytes until 64-bit file size issues are fixed.
+      int64_t toCopy = std::min<int64_t>(size, mChannelOffset - streamOffset);
+      bytes = std::min(toCopy, int64_t(INT32_MAX));
+      NS_ABORT_IF_FALSE(bytes >= 0 && bytes <= toCopy, "Bytes out of range.");
       memcpy(aBuffer + count,
         reinterpret_cast<char*>(mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes);
     } else {
       if (cacheBlock < 0) {
         // We expect all blocks to be cached! Fail!
         return NS_ERROR_FAILURE;
       }
       int64_t offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock;
--- a/media/libnestegg/include/nestegg-stdint.h
+++ b/media/libnestegg/include/nestegg-stdint.h
@@ -1,7 +1,8 @@
 #ifdef _WIN32
 typedef __int64 int64_t;
 typedef unsigned __int64 uint64_t;
+#define INT64_MAX 9223372036854775807LL
 #else
 #include <stdint.h>
 #endif
 
--- a/media/libnestegg/src/nestegg.c
+++ b/media/libnestegg/src/nestegg.c
@@ -2101,16 +2101,19 @@ nestegg_get_cue_point(nestegg * ctx, uns
   return 0;
 }
 
 int
 nestegg_offset_seek(nestegg * ctx, uint64_t offset)
 {
   int r;
 
+  if (offset > INT64_MAX)
+    return -1;
+
   /* Seek and set up parser state for segment-level element (Cluster). */
   r = ne_io_seek(ctx->io, offset, NESTEGG_SEEK_SET);
   if (r != 0)
     return -1;
   ctx->last_valid = 0;
 
   while (ctx->ancestor)
     ne_ctx_pop(ctx);