Chromium Code Reviews| Index: third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoder.cpp |
| diff --git a/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoder.cpp |
| index a189f8104505aafd491d1a17707f087b3fb92063..a4db195a667e0caf044572c25f8887374e568191 100644 |
| --- a/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoder.cpp |
| +++ b/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoder.cpp |
| @@ -83,6 +83,15 @@ bool ICOImageDecoder::setSize(unsigned width, unsigned height) |
| return m_frameSize.isEmpty() ? ImageDecoder::setSize(width, height) : ((IntSize(width, height) == m_frameSize) || setFailed()); |
| } |
| +bool ICOImageDecoder::frameIsFullyReceivedAtIndex(size_t index) const |
| +{ |
| + ASSERT(haveUpdatedFrameCount()); |
| + if (index >= m_dirEntries.size()) |
| + return ImageDecoder::frameIsFullyReceivedAtIndex(index); |
| + const IconDirectoryEntry& dirEntry = m_dirEntries[index]; |
| + return ((dirEntry.m_imageOffset + dirEntry.m_byteSize) <= m_data->size()) || ImageDecoder::frameIsFullyReceivedAtIndex(index); |
| +} |
| + |
| bool ICOImageDecoder::setFailed() |
| { |
| m_bmpReaders.clear(); |
| @@ -107,7 +116,6 @@ bool ICOImageDecoder::hotSpotAtIndex(size_t index, IntPoint& hotSpot) const |
| return true; |
| } |
| - |
| // static |
| bool ICOImageDecoder::compareEntries(const IconDirectoryEntry& a, const IconDirectoryEntry& b) |
| { |
| @@ -120,6 +128,12 @@ bool ICOImageDecoder::compareEntries(const IconDirectoryEntry& a, const IconDire |
| size_t ICOImageDecoder::decodeFrameCount() |
| { |
| decodeSize(); |
| + |
| + for (size_t i = 0; i < m_dirEntries.size(); ++i) { |
| + const IconDirectoryEntry& dirEntry = m_dirEntries[i]; |
| + if ((dirEntry.m_imageOffset + dirEntry.m_byteSize) > m_data->size()) |
|
aleksandar.stojiljkovic
2016/06/06 14:26:39
frameCount should include only fully received fram
|
| + return i + 1; |
| + } |
| return m_dirEntries.size(); |
| } |
| @@ -147,7 +161,7 @@ void ICOImageDecoder::decode(size_t index, bool onlySize) |
| // If we're done decoding this frame, we don't need the BMPImageReader or |
| // PNGImageDecoder anymore. (If we failed, these have already been |
| // cleared.) |
| - } else if ((m_frameBufferCache.size() > index) && (m_frameBufferCache[index].getStatus() == ImageFrame::FrameComplete)) { |
| + } else if (frameIsCompleteAtIndex(index)) { |
| m_bmpReaders[index].clear(); |
| m_pngDecoders[index].clear(); |
| } |
| @@ -171,15 +185,15 @@ bool ICOImageDecoder::decodeAtIndex(size_t index) |
| if (imageType == Unknown) |
| return false; // Not enough data to determine image type yet. |
| + ASSERT(m_frameBufferCache.size() == decodeFrameCount()); |
|
aleksandar.stojiljkovic
2016/06/06 14:26:39
this assert is copied from previous code but is no
|
| if (imageType == BMP) { |
| if (!m_bmpReaders[index]) { |
| - // We need to have already sized m_frameBufferCache before this, and |
| - // we must not resize it again later (see caution in frameCount()). |
| - ASSERT(m_frameBufferCache.size() == m_dirEntries.size()); |
| m_bmpReaders[index] = adoptPtr(new BMPImageReader(this, dirEntry.m_imageOffset, 0, true)); |
| m_bmpReaders[index]->setData(m_data.get()); |
| - m_bmpReaders[index]->setBuffer(&m_frameBufferCache[index]); |
| } |
| + // Update the pointer to the buffer as it could change after |
| + // m_frameBufferCache.resize(). |
| + m_bmpReaders[index]->setBuffer(&m_frameBufferCache[index]); |
| m_frameSize = dirEntry.m_size; |
| bool result = m_bmpReaders[index]->decodeBMP(false); |
| m_frameSize = IntSize(); |
| @@ -273,6 +287,7 @@ ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry() |
| entry.m_bitCount = readUint16(6); |
| entry.m_hotSpot = IntPoint(); |
| } |
| + entry.m_byteSize = readUint32(8); |
| entry.m_imageOffset = readUint32(12); |
| // Some icons don't have a bit depth, only a color count. Convert the |