Support pngs with incorrect CMF bytes

Bug: chromium:807324

Though these pngs are technically incorrect, many such PNGs exist, and
they are supported in Chromium. Ensure that users of SkCodec (e.g.
Android, Flutter) display them as well.

Change-Id: I2f1e573b4b7039cea81f96397cc0aa4cbc9461c3
Reviewed-on: https://skia-review.googlesource.com/111082
Commit-Queue: Leon Scroggins <scroggo@google.com>
Reviewed-by: Derek Sollenberger <djsollen@google.com>
diff --git a/resources/images/crbug807324.png b/resources/images/crbug807324.png
new file mode 100644
index 0000000..f58aab7
--- /dev/null
+++ b/resources/images/crbug807324.png
Binary files differ
diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp
index 9df7bc6..df22121 100644
--- a/src/codec/SkPngCodec.cpp
+++ b/src/codec/SkPngCodec.cpp
@@ -22,6 +22,7 @@
 #include "SkTemplates.h"
 #include "SkUtils.h"
 
+#define PNG_SET_OPTION_SUPPORTED
 #include "png.h"
 #include <algorithm>
 
@@ -787,6 +788,10 @@
         return SkCodec::kInternalError;
     }
 
+    // This setting ensures that we display images with incorrect CMF bytes.
+    // See crbug.com/807324.
+    png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON);
+
     AutoCleanPng autoClean(png_ptr, stream, chunkReader, outCodec);
 
     png_infop info_ptr = png_create_info_struct(png_ptr);
diff --git a/tests/CodecTest.cpp b/tests/CodecTest.cpp
index e3362f5..d8dab25 100644
--- a/tests/CodecTest.cpp
+++ b/tests/CodecTest.cpp
@@ -1566,3 +1566,38 @@
         }
     }
 }
+
+DEF_TEST(Codec_crbug807324, r) {
+    if (GetResourcePath().isEmpty()) {
+        return;
+    }
+
+    const char* file = "images/crbug807324.png";
+    auto image = GetResourceAsImage(file);
+    if (!image) {
+        ERRORF(r, "Missing %s", file);
+        return;
+    }
+
+    const int kWidth = image->width();
+    const int kHeight = image->height();
+
+    SkBitmap bm;
+    if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(kWidth, kHeight))) {
+        ERRORF(r, "Could not allocate pixels (%i x %i)", kWidth, kHeight);
+        return;
+    }
+
+    bm.eraseColor(SK_ColorTRANSPARENT);
+
+    SkCanvas canvas(bm);
+    canvas.drawImage(image, 0, 0, nullptr);
+
+    for (int i = 0; i < kWidth;  ++i)
+    for (int j = 0; j < kHeight; ++j) {
+        if (*bm.getAddr32(i, j) == SK_ColorTRANSPARENT) {
+            ERRORF(r, "image should not be transparent! %i, %i is 0", i, j);
+            return;
+        }
+    }
+}
diff --git a/third_party/libpng/BUILD.gn b/third_party/libpng/BUILD.gn
index a01ede6..2b2d72a 100644
--- a/third_party/libpng/BUILD.gn
+++ b/third_party/libpng/BUILD.gn
@@ -20,7 +20,7 @@
       "../externals/libpng",
     ]
 
-    defines = []
+    defines = [ "PNG_SET_OPTION_SUPPORTED" ]
     deps = [
       "//third_party/zlib",
     ]