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

Unified Diff: src/codec/SkCodec_libpng.cpp

Issue 1055743003: Swizzler changes Index8 and 565 (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Avoid setting a field to a local variable Created 5 years, 9 months 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
Index: src/codec/SkCodec_libpng.cpp
diff --git a/src/codec/SkCodec_libpng.cpp b/src/codec/SkCodec_libpng.cpp
index 33111cee67841938335fd6f7b0862d5f9ec0a9c6..819ade55df079b0d1f05de936640330f6200b3ec 100644
--- a/src/codec/SkCodec_libpng.cpp
+++ b/src/codec/SkCodec_libpng.cpp
@@ -15,6 +15,7 @@
#include "SkSize.h"
#include "SkStream.h"
#include "SkSwizzler.h"
+#include "SkUtils.h"
///////////////////////////////////////////////////////////////////////////////
// Helper macros
@@ -119,7 +120,7 @@ typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
// Note: SkColorTable claims to store SkPMColors, which is not necessarily
// the case here.
-bool SkPngCodec::decodePalette(bool premultiply) {
+bool SkPngCodec::decodePalette(bool premultiply, int bitDepth, int* ctableCount) {
int numPalette;
png_colorp palette;
png_bytep trans;
@@ -128,14 +129,7 @@ bool SkPngCodec::decodePalette(bool premultiply) {
return false;
}
- /* 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.
- */
- const int colorCount = numPalette + (numPalette < 256);
- // Note: These are not necessarily SkPMColors.
+ // Note: These are not necessarily SkPMColors
SkPMColor colorStorage[256]; // worst-case storage
SkPMColor* colorPtr = colorStorage;
@@ -175,9 +169,24 @@ bool SkPngCodec::decodePalette(bool premultiply) {
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;
+ }
+
+ // Set the new color count
+ if (ctableCount != NULL) {
+ SkASSERT(256 == *ctableCount);
+ *ctableCount = colorCount;
}
fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorStorage, colorCount)));
@@ -276,10 +285,7 @@ static bool read_header(SkStream* stream, png_structp* png_ptrp,
SkAlphaType skAlphaType;
switch (colorType) {
case PNG_COLOR_TYPE_PALETTE:
- // Technically, this is true of the data, but I don't think we want
- // to support it.
- // skColorType = kIndex8_SkColorType;
- skColorType = kN32_SkColorType;
+ skColorType = kIndex_8_SkColorType;
skAlphaType = has_transparency_in_palette(png_ptr, info_ptr) ?
kUnpremul_SkAlphaType : kOpaque_SkAlphaType;
break;
@@ -401,7 +407,8 @@ static bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src)
SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo,
void* dst, size_t rowBytes,
- const Options& options) {
+ const Options& options,
+ int* ctableCount) {
// FIXME: Could we use the return value of setjmp to specify the type of
// error?
if (setjmp(png_jmpbuf(fPng_ptr))) {
@@ -422,7 +429,8 @@ SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo,
fReallyHasAlpha = false;
if (PNG_COLOR_TYPE_PALETTE == pngColorType) {
fSrcConfig = SkSwizzler::kIndex;
- if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaType())) {
+ if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaType(), bitDepth,
+ ctableCount)) {
return kInvalidInput;
}
} else if (kAlpha_8_SkColorType == requestedInfo.colorType()) {
@@ -491,8 +499,18 @@ SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void*
return kInvalidConversion;
}
+ // Note that ctableCount will be modified if there is a color table
const Result result = this->initializeSwizzler(requestedInfo, dst, rowBytes,
- options);
+ options, ctableCount);
+
+ // Copy the color table to the client if necessary
+ if (kIndex_8_SkColorType == requestedInfo.colorType()) {
+ SkASSERT(NULL != ctable);
+ SkASSERT(NULL != ctableCount);
+ SkASSERT(NULL != fColorTable.get());
+ sk_memcpy32(ctable, fColorTable->readColors(), *ctableCount);
msarett 2015/04/03 18:01:32 Is this better than using regular memcpy?
scroggo 2015/04/06 14:55:11 We have MemoryBench which compares the two, and it
msarett 2015/04/06 18:10:55 Acknowledged.
+ }
+
if (result != kSuccess) {
return result;
}
@@ -630,7 +648,7 @@ SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo)
Options opts;
// FIXME: Pass this in to getScanlineDecoder?
opts.fZeroInitialized = kNo_ZeroInitialized;
- if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), opts) != kSuccess) {
+ if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), opts, NULL) != kSuccess) {
scroggo 2015/04/06 14:55:11 Maybe add a FIXME acknowledging that getScanlineDe
msarett 2015/04/06 18:10:55 Done.
SkCodecPrintf("failed to initialize the swizzler.\n");
return NULL;
}

Powered by Google App Engine
This is Rietveld 408576698