| Index: src/codec/SkBmpRLECodec.cpp | 
| diff --git a/src/codec/SkBmpRLECodec.cpp b/src/codec/SkBmpRLECodec.cpp | 
| index 828871cd547be98ef2b6bc537d2ec5c3b2b9e688..86b64e229fea27a0e84c2ae9a2970f35411226cf 100644 | 
| --- a/src/codec/SkBmpRLECodec.cpp | 
| +++ b/src/codec/SkBmpRLECodec.cpp | 
| @@ -183,6 +183,41 @@ bool SkBmpRLECodec::initializeStreamBuffer() { | 
| } | 
|  | 
| /* | 
| + * Before signalling kIncompleteInput, we should attempt to load the | 
| + * stream buffer with additional data. | 
| + * | 
| + * @return the number of bytes remaining in the stream buffer after | 
| + *         attempting to read more bytes from the stream | 
| + */ | 
| +size_t SkBmpRLECodec::checkForMoreData() { | 
| +    const size_t remainingBytes = fRLEBytes - fCurrRLEByte; | 
| +    uint8_t* buffer = fStreamBuffer.get(); | 
| + | 
| +    // We will be reusing the same buffer, starting over from the beginning. | 
| +    // Move any remaining bytes to the start of the buffer. | 
| +    // We use memmove() instead of memcpy() because there is risk that the dst | 
| +    // and src memory will overlap in corrupt images. | 
| +    memmove(buffer, SkTAddOffset<uint8_t>(buffer, fCurrRLEByte), remainingBytes); | 
| + | 
| +    // Adjust the buffer ptr to the start of the unfilled data. | 
| +    buffer += remainingBytes; | 
| + | 
| +    // Try to read additional bytes from the stream.  There are fCurrRLEByte | 
| +    // bytes of additional space remaining in the buffer, assuming that we | 
| +    // have already copied remainingBytes to the start of the buffer. | 
| +    size_t additionalBytes = this->stream()->read(buffer, fCurrRLEByte); | 
| + | 
| +    // Update counters and return the number of bytes we currently have | 
| +    // available.  We are at the start of the buffer again. | 
| +    fCurrRLEByte = 0; | 
| +    // If we were unable to fill the buffer, fRLEBytes is no longer equal to | 
| +    // the size of the buffer.  There will be unused space at the end.  This | 
| +    // should be fine, given that there are no more bytes in the stream. | 
| +    fRLEBytes = remainingBytes + additionalBytes; | 
| +    return fRLEBytes; | 
| +} | 
| + | 
| +/* | 
| * Set an RLE pixel using the color table | 
| */ | 
| void SkBmpRLECodec::setPixel(void* dst, size_t dstRowBytes, | 
| @@ -287,8 +322,10 @@ SkCodec::Result SkBmpRLECodec::decode(const SkImageInfo& dstInfo, | 
|  | 
| // Every entry takes at least two bytes | 
| if ((int) fRLEBytes - fCurrRLEByte < 2) { | 
| -            SkCodecPrintf("Warning: incomplete RLE input.\n"); | 
| -            return kIncompleteInput; | 
| +            SkCodecPrintf("Warning: might be incomplete RLE input.\n"); | 
| +            if (this->checkForMoreData() < 2) { | 
| +                return kIncompleteInput; | 
| +            } | 
| } | 
|  | 
| // Read the next two bytes.  These bytes have different meanings | 
| @@ -310,8 +347,10 @@ SkCodec::Result SkBmpRLECodec::decode(const SkImageInfo& dstInfo, | 
| case RLE_DELTA: { | 
| // Two bytes are needed to specify delta | 
| if ((int) fRLEBytes - fCurrRLEByte < 2) { | 
| -                        SkCodecPrintf("Warning: incomplete RLE input\n"); | 
| -                        return kIncompleteInput; | 
| +                        SkCodecPrintf("Warning: might be incomplete RLE input.\n"); | 
| +                        if (this->checkForMoreData() < 2) { | 
| +                            return kIncompleteInput; | 
| +                        } | 
| } | 
| // Modify x and y | 
| const uint8_t dx = fStreamBuffer.get()[fCurrRLEByte++]; | 
| @@ -319,8 +358,8 @@ SkCodec::Result SkBmpRLECodec::decode(const SkImageInfo& dstInfo, | 
| x += dx; | 
| y += dy; | 
| if (x > width || y > height) { | 
| -                        SkCodecPrintf("Warning: invalid RLE input 1.\n"); | 
| -                        return kIncompleteInput; | 
| +                        SkCodecPrintf("Warning: invalid RLE input.\n"); | 
| +                        return kInvalidInput; | 
| } | 
| break; | 
| } | 
| @@ -333,12 +372,18 @@ SkCodec::Result SkBmpRLECodec::decode(const SkImageInfo& dstInfo, | 
| const size_t rowBytes = compute_row_bytes(numPixels, | 
| this->bitsPerPixel()); | 
| // Abort if setting numPixels moves us off the edge of the | 
| -                    // image.  Also abort if there are not enough bytes | 
| +                    // image. | 
| +                    if (x + numPixels > width) { | 
| +                        SkCodecPrintf("Warning: invalid RLE input.\n"); | 
| +                        return kInvalidInput; | 
| +                    } | 
| +                    // Also abort if there are not enough bytes | 
| // remaining in the stream to set numPixels. | 
| -                    if (x + numPixels > width || | 
| -                            (int) fRLEBytes - fCurrRLEByte < SkAlign2(rowBytes)) { | 
| -                        SkCodecPrintf("Warning: invalid RLE input 2.\n"); | 
| -                        return kIncompleteInput; | 
| +                    if ((int) fRLEBytes - fCurrRLEByte < SkAlign2(rowBytes)) { | 
| +                        SkCodecPrintf("Warning: might be incomplete RLE input.\n"); | 
| +                        if (this->checkForMoreData() < SkAlign2(rowBytes)) { | 
| +                            return kIncompleteInput; | 
| +                        } | 
| } | 
| // Set numPixels number of pixels | 
| while (numPixels > 0) { | 
| @@ -394,8 +439,10 @@ SkCodec::Result SkBmpRLECodec::decode(const SkImageInfo& dstInfo, | 
| // There are two more required bytes to finish encoding the | 
| // color. | 
| if ((int) fRLEBytes - fCurrRLEByte < 2) { | 
| -                    SkCodecPrintf("Warning: incomplete RLE input\n"); | 
| -                    return kIncompleteInput; | 
| +                    SkCodecPrintf("Warning: might be incomplete RLE input.\n"); | 
| +                    if (this->checkForMoreData() < 2) { | 
| +                        return kIncompleteInput; | 
| +                    } | 
| } | 
|  | 
| // Fill the pixels up to endX with the specified color | 
|  |