Bug 1242093 - Fix assertion in Downscaler::ClearRow. r=njn
authorTimothy Nikkel <tnikkel@gmail.com>
Tue, 16 Feb 2016 08:04:57 +0100
changeset 331234 f5df9f4596dc4276676257d98d50707da6f97395
parent 331233 decfe1d8c927d13abaf5105492eb3477f574da6b
child 331235 03fc467e100217768a96fb5adeb0feda7a21ccfb
push id10938
push userBogdan.Postelnicu@softvision.ro
push dateTue, 16 Feb 2016 15:52:05 +0000
reviewersnjn
bugs1242093
milestone47.0a1
Bug 1242093 - Fix assertion in Downscaler::ClearRow. r=njn The starting column can be the last column, and we handle that correctly. Also split function into ClearRow and ClearRestOfRow.
image/Downscaler.cpp
image/Downscaler.h
image/decoders/nsBMPDecoder.cpp
image/test/crashtests/1242093-1.html
image/test/crashtests/crashtests.list
--- a/image/Downscaler.cpp
+++ b/image/Downscaler.cpp
@@ -197,19 +197,19 @@ GetFilterOffsetAndLength(UniquePtr<skia:
 {
   MOZ_ASSERT(aOutputImagePosition < aFilter->num_values());
   aFilter->FilterForValue(aOutputImagePosition,
                           aFilterOffsetOut,
                           aFilterLengthOut);
 }
 
 void
-Downscaler::ClearRow(uint32_t aStartingAtCol)
+Downscaler::ClearRestOfRow(uint32_t aStartingAtCol)
 {
-  MOZ_ASSERT(int64_t(mOriginalSize.width) > int64_t(aStartingAtCol));
+  MOZ_ASSERT(int64_t(aStartingAtCol) <= int64_t(mOriginalSize.width));
   uint32_t bytesToClear = (mOriginalSize.width - aStartingAtCol)
                         * sizeof(uint32_t);
   memset(mRowBuffer.get() + (aStartingAtCol * sizeof(uint32_t)),
          0, bytesToClear);
 }
 
 void
 Downscaler::CommitRow()
--- a/image/Downscaler.h
+++ b/image/Downscaler.h
@@ -87,18 +87,21 @@ public:
   bool IsFrameComplete() const { return mCurrentInLine >= mOriginalSize.height; }
 
   /// Retrieves the buffer into which the Decoder should write each row.
   uint8_t* RowBuffer()
   {
     return mRowBuffer.get() + mFrameRect.x * sizeof(uint32_t);
   }
 
-  /// Clears the current row buffer (optionally starting at @aStartingAtCol).
-  void ClearRow(uint32_t aStartingAtCol = 0);
+  /// Clears the current row buffer.
+  void ClearRow() { ClearRestOfRow(0); }
+
+  /// Clears the current row buffer starting at @aStartingAtCol.
+  void ClearRestOfRow(uint32_t aStartingAtCol);
 
   /// Signals that the decoder has finished writing a row into the row buffer.
   void CommitRow();
 
   /// Returns true if there is a non-empty invalid rect available.
   bool HasInvalidation() const;
 
   /// Takes the Downscaler's current invalid rect and resets it.
@@ -161,17 +164,18 @@ public:
 
   nsresult BeginFrame(const nsIntSize&, const Maybe<nsIntRect>&, uint8_t*, bool, bool = false)
   {
     return NS_ERROR_FAILURE;
   }
 
   bool IsFrameComplete() const { return false; }
   uint8_t* RowBuffer() { return nullptr; }
-  void ClearRow(uint32_t = 0) { }
+  void ClearRow() { }
+  void ClearRestOfRow(uint32_t) { }
   void CommitRow() { }
   bool HasInvalidation() const { return false; }
   DownscalerInvalidRect TakeInvalidRect() { return DownscalerInvalidRect(); }
   void ResetForNextProgressivePass() { }
   const nsIntSize FrameSize() const { return nsIntSize(0, 0); }
 };
 
 #endif // MOZ_ENABLE_SKIA
--- a/image/decoders/nsBMPDecoder.cpp
+++ b/image/decoders/nsBMPDecoder.cpp
@@ -989,17 +989,17 @@ nsBMPDecoder::ReadRLEDelta(const char* a
   // Delta encoding makes it possible to skip pixels making part of the image
   // transparent.
   MOZ_ASSERT(mMayHaveTransparency);
   mDoesHaveTransparency = true;
 
   if (mDownscaler) {
     // Clear the skipped pixels. (This clears to the end of the row,
     // which is perfect if there's a Y delta and harmless if not).
-    mDownscaler->ClearRow(/* aStartingAtCol = */ mCurrentPos);
+    mDownscaler->ClearRestOfRow(/* aStartingAtCol = */ mCurrentPos);
   }
 
   // Handle the XDelta.
   mCurrentPos += uint8_t(aData[0]);
   if (mCurrentPos > mH.mWidth) {
     mCurrentPos = mH.mWidth;
   }
 
new file mode 100644
--- /dev/null
+++ b/image/test/crashtests/1242093-1.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset='UTF-8'>
+<meta http-equiv='Cache-control' content='no-cache'>
+</head>
+<body>
+<img id='m1' src='data:image/bmp;base64,Qk1mDgAAAAAAAHYAAAAoAAAAQAEAAPAAAAABAAQAAgAAAPANAADoAwAA6AMAABAAAAAAAAAA/wD/AAAAAAAAAP8AAP8AAP8AAAD///8AzMzMAMzMzADMzMwAzMzMAMzMzADMzMwAzMzMAMzMzADMzMwAzMzMAAACAAEAAgABAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAAAAAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRCAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBpRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAIAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICAGgiAAJqAGpEAAAAAgIAaCIAAmoAakQAAAACAgBoIgACagBqRAAAAAICADgRMCIAAmoAakQAAAACAgA4ETAiAAJqAGpEAAAAAgIABhEBVQURA1UDEQFVCREEVQIRBFUCEQFVCBEBVQYRMCIAAmoAakQAAAACAgAGEQFVBBEBVQMRAVUCEQFVCREBVQURAVUFEQFVCBEBVQYRMCIAAmoAakQAAAACAgAGEQFVBBEBVQMRAVUCEQFVCREBVQURAVUFEQFVCBEBVQYRMCIAAmoAakQAAAACAgAGEQFVBBEBVQMRAVUCEQRVBhEBVQURA1UDEQNVBhEBVQYRMCIAAmoAakQAAAACAgAGEQFVBBEBVQMRAVUCEQFVAxEBVQURAVUFEQFVBREBVQgRAVUGETAiAAJqAGpEAAAAAgIABhEBVQQRAVUDEQFVAhEBVQMRAVUFEQFVBREBVQURAVUIEQFVBhEwIgACagBqRAAAAAICAAMRB1UCEQNVAxEEVQYRAVUFEQRVAhEEVQIRB1UDETAiAAJqAGpEAAAAAgIAOBEwIgACagBqRAAAAAICADgRMCIAAmoAakQAAAACAAEAAgABAAE='>
+<img id='m2' height='2' width='2'>
+<canvas id='c1'></canvas>
+<script>
+  var im1=document.getElementById('m1');
+  var im2=document.getElementById('m2');
+  im2.src=im1.src;
+  window.onload=function(){
+    var ctx=document.getElementById('c1').getContext('2d');
+    ctx.drawImage(im1, 0, 0); // sync docoder call
+    ctx.drawImage(im2, 0, 0); // sync downscaler call
+  }
+</script>
+</body>
+</html>
\ No newline at end of file
--- a/image/test/crashtests/crashtests.list
+++ b/image/test/crashtests/crashtests.list
@@ -12,16 +12,17 @@ load 732319-1.html
 load 844403-1.html
 load 856616.gif
 skip-if(B2G) load 944353.jpg
 load 1205923-1.html
 load 1212954-1.svg
 load 1235605.gif
 load 1241728-1.html
 load 1241729-1.html
+load 1242093-1.html
 load 1242778-1.png
 load colormap-range.gif
 HTTP load delayedframe.sjs # A 3-frame animated GIF with an inordinate delay between the second and third frame
 
 # Animated gifs with a very large canvas, but tiny actual content.
 skip-if(B2G) load delaytest.html?523528-1.gif
 skip-if(B2G) load delaytest.html?523528-2.gif