| Index: Source/core/platform/image-decoders/gif/GIFImageReader.cpp
|
| diff --git a/Source/core/platform/image-decoders/gif/GIFImageReader.cpp b/Source/core/platform/image-decoders/gif/GIFImageReader.cpp
|
| index bf18bea6229c14235b8fe8dda21906dea097b8cd..b933855fa4c0398ac8e6e91c9b77f6633db5c8dd 100644
|
| --- a/Source/core/platform/image-decoders/gif/GIFImageReader.cpp
|
| +++ b/Source/core/platform/image-decoders/gif/GIFImageReader.cpp
|
| @@ -98,7 +98,7 @@ using WebCore::GIFImageDecoder;
|
| #define GETINT16(p) ((p)[1]<<8|(p)[0])
|
|
|
| // Send the data to the display front-end.
|
| -bool GIFLZWContext::outputRow()
|
| +bool GIFLZWContext::outputRow(GIFRow::const_iterator rowBegin)
|
| {
|
| int drowStart = irow;
|
| int drowEnd = irow;
|
| @@ -148,7 +148,7 @@ bool GIFLZWContext::outputRow()
|
| return true;
|
|
|
| // CALLBACK: Let the client know we have decoded a row.
|
| - if (!m_client->haveDecodedRow(m_frameContext->frameId(), rowBuffer, m_frameContext->width(),
|
| + if (!m_client->haveDecodedRow(m_frameContext->frameId(), rowBegin, m_frameContext->width(),
|
| drowStart, drowEnd - drowStart + 1, m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass > 1))
|
| return false;
|
|
|
| @@ -202,24 +202,12 @@ bool GIFLZWContext::outputRow()
|
| // Otherwise, decoding failed; returns false in this case, which will always cause the GIFImageReader to set the "decode failed" flag.
|
| bool GIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock)
|
| {
|
| - int code;
|
| - int incode;
|
| - const unsigned char *ch;
|
| + const size_t width = m_frameContext->width();
|
|
|
| if (rowIter == rowBuffer.end())
|
| return true;
|
|
|
| -#define OUTPUT_ROW \
|
| - do { \
|
| - if (!outputRow()) \
|
| - return false; \
|
| - rowsRemaining--; \
|
| - rowIter = rowBuffer.begin(); \
|
| - if (!rowsRemaining) \
|
| - return true; \
|
| - } while (0)
|
| -
|
| - for (ch = block; bytesInBlock-- > 0; ch++) {
|
| + for (const unsigned char* ch = block; bytesInBlock-- > 0; ch++) {
|
| // Feed the next byte into the decoder's 32-bit input buffer.
|
| datum += ((int) *ch) << bits;
|
| bits += 8;
|
| @@ -227,7 +215,7 @@ bool GIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock)
|
| // Check for underflow of decoder's 32-bit input buffer.
|
| while (bits >= codesize) {
|
| // Get the leading variable-length symbol from the data stream.
|
| - code = datum & codemask;
|
| + int code = datum & codemask;
|
| datum >>= codesize;
|
| bits -= codesize;
|
|
|
| @@ -248,66 +236,72 @@ bool GIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock)
|
| return false;
|
| }
|
|
|
| - if (oldcode == -1) {
|
| - *rowIter++ = suffix[code];
|
| - if (rowIter == rowBuffer.end())
|
| - OUTPUT_ROW;
|
| -
|
| - firstchar = oldcode = code;
|
| - continue;
|
| - }
|
| -
|
| - incode = code;
|
| - if (code >= avail) {
|
| - stack[stackp++] = firstchar;
|
| + const int tempCode = code;
|
| + unsigned short codeLength = 0;
|
| + if (code < avail) {
|
| + // This is a pre-existing code, so we already know what it
|
| + // encodes.
|
| + codeLength = suffixLength[code];
|
| + rowIter += codeLength;
|
| + } else if (code == avail && oldcode != -1) {
|
| + // This is a new code just being added to the dictionary.
|
| + // It must encode the contents of the previous code, plus
|
| + // the first character of the previous code again.
|
| + codeLength = suffixLength[oldcode] + 1;
|
| + rowIter += codeLength;
|
| + *--rowIter = firstchar;
|
| code = oldcode;
|
| -
|
| - if (stackp == MAX_BYTES)
|
| - return false;
|
| + } else {
|
| + // This is an invalid code. The dictionary is just initialized
|
| + // and the code is incomplete. We don't know how to handle
|
| + // this case.
|
| + return false;
|
| }
|
|
|
| while (code >= clearCode) {
|
| - if (code >= MAX_BYTES || code == prefix[code])
|
| - return false;
|
| -
|
| - // Even though suffix[] only holds characters through suffix[avail - 1],
|
| - // allowing code >= avail here lets us be more tolerant of malformed
|
| - // data. As long as code < MAX_BYTES, the only risk is a garbled image,
|
| - // which is no worse than refusing to display it.
|
| - stack[stackp++] = suffix[code];
|
| + *--rowIter = suffix[code];
|
| code = prefix[code];
|
| -
|
| - if (stackp == MAX_BYTES)
|
| - return false;
|
| }
|
|
|
| - stack[stackp++] = firstchar = suffix[code];
|
| + *--rowIter = firstchar = suffix[code];
|
|
|
| - // Define a new codeword in the dictionary.
|
| - if (avail < 4096) {
|
| + // Define a new codeword in the dictionary as long as we've read
|
| + // more than one value from the stream.
|
| + if (avail < MAX_DICTIONARY_ENTRIES && oldcode != -1) {
|
| prefix[avail] = oldcode;
|
| suffix[avail] = firstchar;
|
| - avail++;
|
| + suffixLength[avail] = suffixLength[oldcode] + 1;
|
| + ++avail;
|
|
|
| // If we've used up all the codewords of a given length
|
| // increase the length of codewords by one bit, but don't
|
| - // exceed the specified maximum codeword size of 12 bits.
|
| - if ((!(avail & codemask)) && (avail < 4096)) {
|
| - codesize++;
|
| + // exceed the specified maximum codeword size.
|
| + if (!(avail & codemask) && avail < MAX_DICTIONARY_ENTRIES) {
|
| + ++codesize;
|
| codemask += avail;
|
| }
|
| }
|
| - oldcode = incode;
|
| -
|
| - // Copy the decoded data out to the scanline buffer.
|
| - do {
|
| - *rowIter++ = stack[--stackp];
|
| - if (rowIter == rowBuffer.end())
|
| - OUTPUT_ROW;
|
| - } while (stackp > 0);
|
| + oldcode = tempCode;
|
| + rowIter += codeLength;
|
| +
|
| + // Output as many rows as possible.
|
| + GIFRow::iterator rowBegin = rowBuffer.begin();
|
| + for (; rowBegin + width <= rowIter; rowBegin += width) {
|
| + if (!outputRow(rowBegin))
|
| + return false;
|
| + rowsRemaining--;
|
| + if (!rowsRemaining)
|
| + return true;
|
| + }
|
| +
|
| + if (rowBegin != rowBuffer.begin()) {
|
| + // Move the remaining bytes to the beginning of the buffer.
|
| + const size_t bytesToCopy = rowIter - rowBegin;
|
| + memcpy(rowBuffer.begin(), rowBegin, bytesToCopy);
|
| + rowIter = rowBuffer.begin() + bytesToCopy;
|
| + }
|
| }
|
| }
|
| -
|
| return true;
|
| }
|
|
|
| @@ -316,12 +310,12 @@ void GIFColorMap::buildTable(const unsigned char* data, size_t length)
|
| if (!m_isDefined || !m_table.isEmpty())
|
| return;
|
|
|
| - RELEASE_ASSERT(m_position + m_colors * GIF_COLORS <= length);
|
| + RELEASE_ASSERT(m_position + m_colors * BYTES_PER_COLORMAP_ENTRY <= length);
|
| const unsigned char* srcColormap = data + m_position;
|
| m_table.resize(m_colors);
|
| for (Table::iterator iter = m_table.begin(); iter != m_table.end(); ++iter) {
|
| *iter = SkPackARGB32NoCheck(255, srcColormap[0], srcColormap[1], srcColormap[2]);
|
| - srcColormap += GIF_COLORS;
|
| + srcColormap += BYTES_PER_COLORMAP_ENTRY;
|
| }
|
| }
|
|
|
| @@ -456,7 +450,7 @@ bool GIFImageReader::parseData(size_t dataPosition, size_t len, GIFImageDecoder:
|
|
|
| if ((currentComponent[4] & 0x80) && globalColorMapColors > 0) { /* global map */
|
| m_globalColorMap.setTablePositionAndSize(dataPosition, globalColorMapColors);
|
| - GETN(GIF_COLORS * globalColorMapColors, GIFGlobalColormap);
|
| + GETN(BYTES_PER_COLORMAP_ENTRY * globalColorMapColors, GIFGlobalColormap);
|
| break;
|
| }
|
|
|
| @@ -696,7 +690,7 @@ bool GIFImageReader::parseData(size_t dataPosition, size_t len, GIFImageDecoder:
|
| // The three low-order bits of currentComponent[8] specify the bits per pixel.
|
| const size_t numColors = 2 << (currentComponent[8] & 0x7);
|
| currentFrame->localColorMap().setTablePositionAndSize(dataPosition, numColors);
|
| - GETN(GIF_COLORS * numColors, GIFImageColormap);
|
| + GETN(BYTES_PER_COLORMAP_ENTRY * numColors, GIFImageColormap);
|
| break;
|
| }
|
|
|
| @@ -760,14 +754,10 @@ bool GIFLZWContext::prepareToDecode()
|
| ASSERT(m_frameContext->isDataSizeDefined() && m_frameContext->isHeaderDefined());
|
|
|
| // Since we use a codesize of 1 more than the datasize, we need to ensure
|
| - // that our datasize is strictly less than the MAX_LZW_BITS value (12).
|
| - // This sets the largest possible codemask correctly at 4095.
|
| - if (m_frameContext->dataSize() >= MAX_LZW_BITS)
|
| + // that our datasize is strictly less than the MAX_DICTIONARY_ENTRY_BITS.
|
| + if (m_frameContext->dataSize() >= MAX_DICTIONARY_ENTRY_BITS)
|
| return false;
|
| clearCode = 1 << m_frameContext->dataSize();
|
| - if (clearCode >= MAX_BYTES)
|
| - return false;
|
| -
|
| avail = clearCode + 2;
|
| oldcode = -1;
|
| codesize = m_frameContext->dataSize() + 1;
|
| @@ -776,18 +766,36 @@ bool GIFLZWContext::prepareToDecode()
|
| ipass = m_frameContext->interlaced() ? 1 : 0;
|
| irow = 0;
|
|
|
| - // Initialize output row buffer.
|
| - rowBuffer.resize(m_frameContext->width());
|
| + // We want to know the longest sequence encodable by a dictionary with
|
| + // MAX_DICTIONARY_ENTRIES entries. If we ignore the need to encode the base
|
| + // values themselves at the beginning of the dictionary, as well as the need
|
| + // for a clear code or a termination code, we could use every entry to
|
| + // encode a series of multiple values. If the input value stream looked
|
| + // like "AAAAA..." (a long string of just one value), the first dictionary
|
| + // entry would encode AA, the next AAA, the next AAAA, and so forth. Thus
|
| + // the longest sequence would be MAX_DICTIONARY_ENTRIES + 1 values.
|
| + //
|
| + // However, we have to account for reserved entries. The first |datasize|
|
| + // bits are reserved for the base values, and the next two entries are
|
| + // reserved for the clear code and termination code. In theory a GIF can
|
| + // set the datasize to 0, meaning we have just two reserved entries, making
|
| + // the longest sequence (MAX_DICTIONARY_ENTIRES + 1) - 2 values long. Since
|
| + // each value is a byte, this is also the number of bytes in the longest
|
| + // encodable sequence.
|
| + const size_t maxBytes = MAX_DICTIONARY_ENTRIES - 1;
|
| +
|
| + // Now allocate the output buffer. We decode directly into this buffer
|
| + // until we have at least one row worth of data, then call outputRow().
|
| + // This means worst case we may have (row width - 1) bytes in the buffer
|
| + // and then decode a sequence |maxBytes| long to append.
|
| + rowBuffer.resize(m_frameContext->width() - 1 + maxBytes);
|
| rowIter = rowBuffer.begin();
|
| rowsRemaining = m_frameContext->height();
|
|
|
| // Clearing the whole suffix table lets us be more tolerant of bad data.
|
| - memset(suffix, 0, sizeof(suffix));
|
| -
|
| - // Clearing the whole prefix table to prevent uninitialized access.
|
| - memset(prefix, 0, sizeof(prefix));
|
| - for (int i = 0; i < clearCode; i++)
|
| + for (int i = 0; i < clearCode; ++i) {
|
| suffix[i] = i;
|
| - stackp = 0;
|
| + suffixLength[i] = 1;
|
| + }
|
| return true;
|
| }
|
|
|