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>
diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp
index 6b6ac99..1f69159 100644
--- a/src/codec/SkPngCodec.cpp
+++ b/src/codec/SkPngCodec.cpp
@@ -132,10 +132,11 @@
         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;
diff --git a/tests/CodecPartialTest.cpp b/tests/CodecPartialTest.cpp
index c029922..13cea8a 100644
--- a/tests/CodecPartialTest.cpp
+++ b/tests/CodecPartialTest.cpp
@@ -401,3 +401,28 @@
         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);
+}