Index: src/codec/SkBmpRLECodec.cpp |
diff --git a/src/codec/SkBmpRLECodec.cpp b/src/codec/SkBmpRLECodec.cpp |
index 828871cd547be98ef2b6bc537d2ec5c3b2b9e688..dec4d55c5c1aed891723b63e82a1015746745d0b 100644 |
--- a/src/codec/SkBmpRLECodec.cpp |
+++ b/src/codec/SkBmpRLECodec.cpp |
@@ -183,6 +183,32 @@ bool SkBmpRLECodec::initializeStreamBuffer() { |
} |
/* |
+ * It is possible for an encoded image stream to contain more encoded data than |
+ * it reports that it has. Before signalling kIncompleteInput, we should check |
+ * if we can reset the stream buffer with additional data. |
+ */ |
+size_t SkBmpRLECodec::resetStreamBuffer() { |
+ size_t remainingBytes = fRLEBytes - fCurrRLEByte; |
scroggo
2015/08/07 13:35:35
This can be const?
msarett
2015/08/11 22:35:02
Yes, I have made it const.
|
+ uint8_t* buffer = fStreamBuffer.get(); |
+ |
+ // Store the remaining bytes to the start of our new buffer |
scroggo
2015/08/07 13:35:35
"new" buffer? It is the same buffer, correct?
msarett
2015/08/11 22:35:02
Yes. I have changed the comment to make this make
|
+ for (uint32_t i = 0; i < remainingBytes; i++) { |
scroggo
2015/08/07 13:35:35
Why did you use uint32_t here? remainingBytes is a
msarett
2015/08/11 22:35:02
It should be a size_t. The loop is gone (using me
|
+ buffer[i] = buffer[fCurrRLEByte + i]; |
scroggo
2015/08/07 13:35:35
Are these indices guaranteed to be safe/valid?
Al
msarett
2015/08/11 22:35:03
I think the indices are safe. I have run through
|
+ } |
+ |
+ // Adjust the buffer ptr to the start of the data to be overwritten |
+ buffer += remainingBytes; |
+ |
+ // Try to read additional bytes from the stream |
+ size_t additionalBytes = this->stream()->read(buffer, fRLEBytes - remainingBytes); |
scroggo
2015/08/07 13:35:35
Two thoughts: looking at your calculation above:
msarett
2015/08/11 22:35:02
We will either read to the end of the stream or en
|
+ |
+ // Update counters and return the number of bytes we currently have available |
+ fCurrRLEByte = 0; |
+ fRLEBytes = remainingBytes + additionalBytes; |
scroggo
2015/08/07 13:35:35
So this is now the total bytes that we have read f
msarett
2015/08/11 22:35:02
Yes. fRLEBytes is no longer the size of the buffe
|
+ return fRLEBytes - fCurrRLEByte; |
scroggo
2015/08/07 13:35:35
fCurrRLEByte is 0, so this is just fRLEBytes, righ
msarett
2015/08/11 22:35:02
Yes this is correct.
|
+} |
+ |
+/* |
* Set an RLE pixel using the color table |
*/ |
void SkBmpRLECodec::setPixel(void* dst, size_t dstRowBytes, |
@@ -287,8 +313,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->resetStreamBuffer() < 2) { |
+ return kIncompleteInput; |
+ } |
} |
// Read the next two bytes. These bytes have different meanings |
@@ -310,8 +338,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->resetStreamBuffer() < 2) { |
+ return kIncompleteInput; |
+ } |
} |
// Modify x and y |
const uint8_t dx = fStreamBuffer.get()[fCurrRLEByte++]; |
@@ -319,8 +349,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 +363,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->resetStreamBuffer() < SkAlign2(rowBytes)) { |
+ return kIncompleteInput; |
+ } |
} |
// Set numPixels number of pixels |
while (numPixels > 0) { |
@@ -394,8 +430,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->resetStreamBuffer() < 2) { |
+ return kIncompleteInput; |
+ } |
} |
// Fill the pixels up to endX with the specified color |