Bug 1085175. r=roc, a=dveditz
authorMatthew Gregan <kinetik@flim.org>
Tue, 11 Nov 2014 08:58:52 +1300
changeset 226024 9cd882996cbe
parent 226019 87fd4f56cfed
child 226025 e7f8aa528841
push id4111
push userryanvm@gmail.com
push date2014-11-11 15:36 +0000
treeherdermozilla-beta@e7f8aa528841 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, dveditz
bugs1085175
milestone34.0
Bug 1085175. r=roc, a=dveditz
content/media/MediaCache.cpp
media/libnestegg/include/nestegg-stdint.h
media/libnestegg/src/nestegg.c
--- a/content/media/MediaCache.cpp
+++ b/content/media/MediaCache.cpp
@@ -1169,16 +1169,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
@@ -1697,16 +1698,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);
   }
 }
 
@@ -2121,33 +2123,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
@@ -2179,21 +2186,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;
@@ -2211,17 +2217,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;
@@ -2235,16 +2244,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;
     }
@@ -2271,19 +2281,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;
@@ -2295,28 +2303,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,10 @@
 #ifdef _WIN32
 typedef __int64 int64_t;
 typedef unsigned __int64 uint64_t;
+#if !defined(INT64_MAX)
+#define INT64_MAX 9223372036854775807LL
+#endif
 #else
 #include <stdint.h>
 #endif
 
--- a/media/libnestegg/src/nestegg.c
+++ b/media/libnestegg/src/nestegg.c
@@ -1945,16 +1945,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);