diff options
-rw-r--r-- | resources/invalid_images/ossfuzz6274.gif | bin | 0 -> 45 bytes | |||
-rw-r--r-- | src/codec/SkGifCodec.cpp | 8 | ||||
-rw-r--r-- | tests/CodecTest.cpp | 37 |
3 files changed, 41 insertions, 4 deletions
diff --git a/resources/invalid_images/ossfuzz6274.gif b/resources/invalid_images/ossfuzz6274.gif Binary files differnew file mode 100644 index 0000000000..faa3b6e575 --- /dev/null +++ b/resources/invalid_images/ossfuzz6274.gif diff --git a/src/codec/SkGifCodec.cpp b/src/codec/SkGifCodec.cpp index 1118ed0e7d..dbff9287eb 100644 --- a/src/codec/SkGifCodec.cpp +++ b/src/codec/SkGifCodec.cpp @@ -332,6 +332,8 @@ SkCodec::Result SkGifCodec::onIncrementalDecode(int* rowsDecoded) { SkCodec::Result SkGifCodec::decodeFrame(bool firstAttempt, const Options& opts, int* rowsDecoded) { const SkImageInfo& dstInfo = this->dstInfo(); + const int scaledHeight = get_scaled_dimension(dstInfo.height(), fSwizzler->sampleY()); + const int frameIndex = opts.fFrameIndex; SkASSERT(frameIndex < fReader->imagesCount()); const SkGIFFrameContext* frameContext = fReader->frameContext(frameIndex); @@ -354,8 +356,6 @@ SkCodec::Result SkGifCodec::decodeFrame(bool firstAttempt, const Options& opts, || frameContext->interlaced() || !fCurrColorTableIsReal) { // fill ignores the width (replaces it with the actual, scaled width). // But we need to scale in Y. - const int scaledHeight = get_scaled_dimension(dstInfo.height(), - fSwizzler->sampleY()); auto fillInfo = dstInfo.makeWH(0, scaledHeight); fSwizzler->fill(fillInfo, fDst, fDstRowBytes, this->getFillValue(dstInfo), opts.fZeroInitialized); @@ -370,7 +370,7 @@ SkCodec::Result SkGifCodec::decodeFrame(bool firstAttempt, const Options& opts, fFilledBackground = filledBackground; if (filledBackground) { // Report the full (scaled) height, since the client will never need to fill. - fRowsDecoded = get_scaled_dimension(dstInfo.height(), fSwizzler->sampleY()); + fRowsDecoded = scaledHeight; } else { // This will be updated by haveDecodedRow. fRowsDecoded = 0; @@ -384,7 +384,7 @@ SkCodec::Result SkGifCodec::decodeFrame(bool firstAttempt, const Options& opts, bool frameDecoded = false; const bool fatalError = !fReader->decode(frameIndex, &frameDecoded); - if (fatalError || !frameDecoded) { + if (fatalError || !frameDecoded || fRowsDecoded != scaledHeight) { if (rowsDecoded) { *rowsDecoded = fRowsDecoded; } diff --git a/tests/CodecTest.cpp b/tests/CodecTest.cpp index 290686fa37..6e0a88cd5a 100644 --- a/tests/CodecTest.cpp +++ b/tests/CodecTest.cpp @@ -10,6 +10,7 @@ #include "SkAndroidCodec.h" #include "SkAutoMalloc.h" #include "SkBitmap.h" +#include "SkCanvas.h" #include "SkCodec.h" #include "SkCodecImageGenerator.h" #include "SkColorSpace_XYZ.h" @@ -27,6 +28,7 @@ #include "SkRandom.h" #include "SkStream.h" #include "SkStreamPriv.h" +#include "SkUnPreMultiply.h" #include "SkWebpEncoder.h" #include "Test.h" @@ -1528,3 +1530,38 @@ DEF_TEST(Codec_webp_rowsDecoded, r) { test_info(r, codec.get(), codec->getInfo(), SkCodec::kInvalidInput, nullptr); } + +DEF_TEST(Codec_ossfuzz6274, r) { + if (GetResourcePath().isEmpty()) { + return; + } + + const char* file = "invalid_images/ossfuzz6274.gif"; + auto image = GetResourceAsImage(file); + if (!image) { + ERRORF(r, "Missing %s", file); + return; + } + + REPORTER_ASSERT(r, image->width() == 32); + REPORTER_ASSERT(r, image->height() == 32); + + SkBitmap bm; + if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(32, 32))) { + ERRORF(r, "Failed to allocate pixels"); + return; + } + + bm.eraseColor(SK_ColorTRANSPARENT); + + SkCanvas canvas(bm); + canvas.drawImage(image, 0, 0, nullptr); + + for (int i = 0; i < image->width(); ++i) + for (int j = 0; j < image->height(); ++j) { + SkColor actual = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(i, j)); + if (actual != SK_ColorTRANSPARENT) { + ERRORF(r, "did not initialize pixels! %i, %i is %x", i, j, actual); + } + } +} |