Chromium Code Reviews| Index: src/images/SkImageDecoder_libpng.cpp |
| diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp |
| index f9ef6b7942306016c714668555d96b7c3c31fbb3..53d02dc5f4ce22021a3f37d6308089b3e8498c1b 100644 |
| --- a/src/images/SkImageDecoder_libpng.cpp |
| +++ b/src/images/SkImageDecoder_libpng.cpp |
| @@ -99,7 +99,7 @@ private: |
| bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_ptrp); |
| bool decodePalette(png_structp png_ptr, png_infop info_ptr, |
| bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap, |
| - SkColorTable **colorTablep); |
| + SkColorTable **colorTablep, int bitDepth); |
|
scroggo
2015/03/05 23:23:30
nit: I would prefer to have this new input paramet
David Lattimore
2015/03/06 00:15:26
Done.
|
| bool getBitmapColorType(png_structp, png_infop, SkColorType*, bool* hasAlpha, |
| SkPMColor* theTranspColor); |
| @@ -350,7 +350,7 @@ SkImageDecoder::Result SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap |
| SkColorTable* colorTable = NULL; |
| if (pngColorType == PNG_COLOR_TYPE_PALETTE) { |
| - decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable); |
| + decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable, bitDepth); |
| } |
| SkAutoUnref aur(colorTable); |
| @@ -652,7 +652,7 @@ typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b); |
| bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, |
| bool *hasAlphap, bool *reallyHasAlphap, |
| - SkColorTable **colorTablep) { |
| + SkColorTable **colorTablep, int bitDepth) { |
| int numPalette; |
| png_colorp palette; |
| png_bytep trans; |
| @@ -660,13 +660,6 @@ bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, |
| png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette); |
| - /* BUGGY IMAGE WORKAROUND |
| - |
| - We hit some images (e.g. fruit_.png) who contain bytes that are == colortable_count |
| - which is a problem since we use the byte as an index. To work around this we grow |
| - the colortable by 1 (if its < 256) and duplicate the last color into that slot. |
| - */ |
| - int colorCount = numPalette + (numPalette < 256); |
| SkPMColor colorStorage[256]; // worst-case storage |
| SkPMColor* colorPtr = colorStorage; |
| @@ -705,9 +698,19 @@ bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, |
| palette++; |
| } |
| - // see BUGGY IMAGE WORKAROUND comment above |
| - if (numPalette < 256) { |
| - *colorPtr = colorPtr[-1]; |
| + /* BUGGY IMAGE WORKAROUND |
| + |
| + Invalid images could contain pixel values that are greater than the number of palette |
| + entries. Since we use pixel values as indices into the palette this could result in reading |
| + beyond the end of the palette which could leak the contents of uninitialized memory. To |
| + ensure this doesn't happen, we grow the colortable to the maximum size that can be |
| + addressed by the bitdepth of the image and fill it with the last palette color or black if |
| + the palette is empty (really broken image). |
| + */ |
| + int colorCount = SkTMax(numPalette, 1 << SkTMin(bitDepth, 8)); |
| + SkPMColor lastColor = index > 0 ? colorPtr[-1] : SkPackARGB32(0xFF, 0, 0, 0); |
| + for (; index < colorCount; index++) { |
| + *colorPtr++ = lastColor; |
| } |
| *colorTablep = SkNEW_ARGS(SkColorTable, (colorStorage, colorCount)); |
| @@ -797,7 +800,7 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { |
| SkColorTable* colorTable = NULL; |
| if (pngColorType == PNG_COLOR_TYPE_PALETTE) { |
| - decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable); |
| + decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable, bitDepth); |
| } |
| SkAutoUnref aur(colorTable); |