aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--resources/invalid_images/ossfuzz6274.gifbin0 -> 45 bytes
-rw-r--r--src/codec/SkGifCodec.cpp8
-rw-r--r--tests/CodecTest.cpp37
3 files changed, 41 insertions, 4 deletions
diff --git a/resources/invalid_images/ossfuzz6274.gif b/resources/invalid_images/ossfuzz6274.gif
new file mode 100644
index 0000000000..faa3b6e575
--- /dev/null
+++ b/resources/invalid_images/ossfuzz6274.gif
Binary files differ
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);
+ }
+ }
+}