Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(667)

Unified Diff: src/images/SkImageDecoder_libgif.cpp

Issue 103343006: Sanitize bitmaps produced by libgif (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: comments explaining function Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/images/SkImageDecoder_libgif.cpp
diff --git a/src/images/SkImageDecoder_libgif.cpp b/src/images/SkImageDecoder_libgif.cpp
index f484441c8c3e340d938582eff80c481b538cbf18..a045c27e160799228f1f92dbe0ad791cd179d7e0 100644
--- a/src/images/SkImageDecoder_libgif.cpp
+++ b/src/images/SkImageDecoder_libgif.cpp
@@ -185,6 +185,49 @@ static bool skip_src_rows(GifFileType* gif, uint8_t* dst, int width, int rowsToS
return true;
}
+/**
+ * GIFs with fewer then 256 color entries will sometimes index out of
+ * bounds of the color table (this is malformed, but libgif does not
+ * check sicne it is rare). This function checks for this error and
+ * fixes it. This makes the output image consistantly deterministic.
+ */
+static void sanitize_indexed_bitmap(SkBitmap* bm) {
+ if ((SkBitmap::kIndex8_Config == bm->config()) && !(bm->empty())) {
+ SkAutoLockPixels alp(*bm);
+ if (NULL != bm->getPixels()) {
+ SkColorTable* ct = bm->getColorTable(); // Index8 must have it.
+ SkASSERT(ct != NULL);
+ uint32_t count = ct->count();
+ SkASSERT(count > 0);
+ SkASSERT(count <= 0x100);
+ if (count != 0x100) { // Full colortables can't go wrong.
+ // Count is a power of 2; asserted elsewhere.
+ uint8_t byteMask = (~(count - 1));
+ bool warning = false;
+ uint8_t* addr = static_cast<uint8_t*>(bm->getPixels());
+ int height = bm->height();
+ int width = bm->width();
+ size_t rowBytes = bm->rowBytes();
+ while (--height >= 0) {
+ uint8_t* ptr = addr;
+ int x = width;
+ while (--x >= 0) {
+ if (0 != ((*ptr) & byteMask)) {
+ warning = true;
+ *ptr = 0;
+ }
+ ++ptr;
+ }
+ addr += rowBytes;
+ }
+ if (warning) {
+ gif_warning(*bm, "Index out of bounds.");
+ }
+ }
+ }
+ }
+}
+
bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
#if GIFLIB_MAJOR < 5
GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc);
@@ -289,6 +332,7 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
const ColorMapObject* cmap = find_colormap(gif);
SkAlphaType alphaType = kOpaque_SkAlphaType;
if (cmap != NULL) {
+ SkASSERT(cmap->ColorCount == (1 << (cmap->BitsPerPixel)));
colorCount = cmap->ColorCount;
if (colorCount > 256) {
colorCount = 256; // our kIndex8 can't support more
@@ -410,6 +454,7 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
SkASSERT(read <= innerHeight);
skip_src_rows(gif, scanline, innerWidth, innerHeight - read);
}
+ sanitize_indexed_bitmap(bm);
return true;
} break;
@@ -454,6 +499,7 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
}
} while (recType != TERMINATE_RECORD_TYPE);
+ sanitize_indexed_bitmap(bm);
return true;
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698