Fix decoding incomplete PNG images

If process_data is unable to read (and therefore process) as many bytes
as it expects, process the bytes read before returning false.

Fixes differences in Gold.

Add a test that verifies that it is okay to call png_process_data with
0 bytes. (We could special case 0, but libpng already checks for 0.)

Change-Id: Id500b9305ee3bb6a1a7e8fc70d4e723cb4742b55
Reviewed-on: https://skia-review.googlesource.com/14144
Commit-Queue: Leon Scroggins <scroggo@google.com>
Reviewed-by: Matt Sarett <msarett@google.com>
This commit is contained in:
Leon Scroggins III 2017-04-24 09:32:50 -04:00 committed by Skia Commit-Bot
parent df2bf21364
commit b644650e09
2 changed files with 28 additions and 2 deletions

View File

@ -132,10 +132,11 @@ static inline bool process_data(png_structp png_ptr, png_infop info_ptr,
SkStream* stream, void* buffer, size_t bufferSize, size_t length) {
while (length > 0) {
const size_t bytesToProcess = std::min(bufferSize, length);
if (stream->read(buffer, bytesToProcess) < bytesToProcess) {
const size_t bytesRead = stream->read(buffer, bytesToProcess);
png_process_data(png_ptr, info_ptr, (png_bytep) buffer, bytesRead);
if (bytesRead < bytesToProcess) {
return false;
}
png_process_data(png_ptr, info_ptr, (png_bytep) buffer, bytesToProcess);
length -= bytesToProcess;
}
return true;

View File

@ -401,3 +401,28 @@ DEF_TEST(Codec_GifPreMap, r) {
compare_bitmaps(r, truth, bm);
}
}
DEF_TEST(Codec_emptyIDAT, r) {
const char* name = "baby_tux.png";
sk_sp<SkData> file = GetResourceAsData(name);
if (!file) {
SkDebugf("REMOVE\n");
return;
}
// Truncate to the beginning of the IDAT, immediately after the IDAT tag.
file = SkData::MakeSubset(file.get(), 0, 80);
std::unique_ptr<SkCodec> codec(SkCodec::NewFromData(std::move(file)));
if (!codec) {
ERRORF(r, "Failed to create a codec for %s", name);
return;
}
SkBitmap bm;
const auto info = standardize_info(codec.get());
bm.allocPixels(info);
const auto result = codec->getPixels(info, bm.getPixels(), bm.rowBytes());
REPORTER_ASSERT(r, SkCodec::kIncompleteInput == result);
}