Fix rewinding bug in SkJpegCodec

Performing a sampled and/or subset decode will create some state
in SkJpegCodec.  If we fail to clean up this state properly,
subsequent decodes may try to reuse (and potentailly overflow)
the leftover memory.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2161593003

Committed: https://skia.googlesource.com/skia/+/4ecb8ab556214c9337f56bc36d50e4d7c655ac7a
Review-Url: https://codereview.chromium.org/2161593003
This commit is contained in:
msarett 2016-07-18 15:56:08 -07:00 committed by Commit bot
parent 401ae2d2a0
commit 2812f03d54
2 changed files with 35 additions and 5 deletions

View File

@ -263,6 +263,7 @@ SkJpegCodec::SkJpegCodec(int width, int height, const SkEncodedInfo& info, SkStr
: INHERITED(width, height, info, stream, std::move(colorSpace), origin)
, fDecoderMgr(decoderMgr)
, fReadyState(decoderMgr->dinfo()->global_state)
, fSrcRow(nullptr)
, fSwizzlerSubset(SkIRect::MakeEmpty())
, fICCData(std::move(iccData))
{}
@ -339,6 +340,11 @@ bool SkJpegCodec::onRewind() {
}
SkASSERT(nullptr != decoderMgr);
fDecoderMgr.reset(decoderMgr);
fSwizzler.reset(nullptr);
fSrcRow = nullptr;
fStorage.reset();
return true;
}
@ -588,11 +594,6 @@ SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
return kInvalidConversion;
}
// Remove objects used for sampling.
fSwizzler.reset(nullptr);
fSrcRow = nullptr;
fStorage.reset();
// Now, given valid output dimensions, we can start the decompress
if (!jpeg_start_decompress(fDecoderMgr->dinfo())) {
SkCodecPrintf("start decompress failed\n");

View File

@ -1012,3 +1012,32 @@ DEF_TEST(Codec_wbmp_max_size, r) {
REPORTER_ASSERT(r, !codec);
}
DEF_TEST(Codec_jpeg_rewind, r) {
const char* path = "mandrill_512_q075.jpg";
SkAutoTDelete<SkStream> stream(resource(path));
if (!stream) {
SkDebugf("Missing resource '%s'\n", path);
return;
}
SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(stream.release()));
if (!codec) {
ERRORF(r, "Unable to create codec '%s'.", path);
return;
}
const int width = codec->getInfo().width();
const int height = codec->getInfo().height();
size_t rowBytes = sizeof(SkPMColor) * width;
SkAutoMalloc pixelStorage(height * rowBytes);
// Perform a sampled decode.
SkAndroidCodec::AndroidOptions opts;
opts.fSampleSize = 12;
codec->getAndroidPixels(codec->getInfo().makeWH(width / 12, height / 12), pixelStorage.get(),
rowBytes, &opts);
// Rewind the codec and perform a full image decode.
SkCodec::Result result = codec->getPixels(codec->getInfo(), pixelStorage.get(), rowBytes);
REPORTER_ASSERT(r, SkCodec::kSuccess == result);
}