Bug 1237171 - Improve a case where ICO and BMP files disagree on an image size. r=tn, a=sylvestre
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 07 Jan 2016 16:18:22 -0800
changeset 306014 40e457de9ce8b1a167caf74d9e464d1d51e4fda7
parent 306013 ee238b4680f6155429623f847e2145478c86fb52
child 306015 5f710db3511f8a23a31f12e1aea5ef4af3886359
child 306017 94987e23aa720af290174d37d94e7bd2dc5c3dbb
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn, sylvestre
bugs1237171
milestone44.0
Bug 1237171 - Improve a case where ICO and BMP files disagree on an image size. r=tn, a=sylvestre
image/decoders/nsBMPDecoder.cpp
--- a/image/decoders/nsBMPDecoder.cpp
+++ b/image/decoders/nsBMPDecoder.cpp
@@ -712,26 +712,39 @@ nsBMPDecoder::ReadColorTable(const char*
   }
   uint32_t gapLength = mH.mDataOffset - mPreGapLength;
   return Transition::To(State::GAP, gapLength);
 }
 
 LexerTransition<nsBMPDecoder::State>
 nsBMPDecoder::SkipGap()
 {
+  // If there are no pixels we can stop.
+  //
+  // XXX: normally, if there are no pixels we will have stopped decoding before
+  // now, outside of this decoder. However, if the BMP is within an ICO file,
+  // it's possible that the ICO claimed the image had a non-zero size while the
+  // BMP claims otherwise. This test is to catch that awkward case. If we ever
+  // come up with a more general solution to this ICO-and-BMP-disagree-on-size
+  // problem, this test can be removed.
+  if (mH.mWidth == 0 || mH.mHeight == 0) {
+    return Transition::Terminate(State::SUCCESS);
+  }
+
   bool hasRLE = mH.mCompression == Compression::RLE8 ||
                 mH.mCompression == Compression::RLE4;
   return hasRLE
        ? Transition::To(State::RLE_SEGMENT, RLE::SEGMENT_LENGTH)
        : Transition::To(State::PIXEL_ROW, mPixelRowSize);
 }
 
 LexerTransition<nsBMPDecoder::State>
 nsBMPDecoder::ReadPixelRow(const char* aData)
 {
+  MOZ_ASSERT(mCurrentRow > 0);
   MOZ_ASSERT(mCurrentPos == 0);
 
   const uint8_t* src = reinterpret_cast<const uint8_t*>(aData);
   uint32_t* dst = RowBuffer();
   uint32_t lpos = mH.mWidth;
   switch (mH.mBpp) {
     case 1:
       while (lpos > 0) {