Use spans in testing/image_diff/image_diff_png.h and related code.

Change all the PNG encode functions to use pdfium::span. Update callers
as well.

Change-Id: Ic57e5a8c3518e9a0a56e829ac5ba7c92c995aaa6
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/64370
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/samples/pdfium_test_write_helper.cc b/samples/pdfium_test_write_helper.cc
index 6977707..122d783 100644
--- a/samples/pdfium_test_write_helper.cc
+++ b/samples/pdfium_test_write_helper.cc
@@ -25,7 +25,7 @@
 bool CheckDimensions(int stride, int width, int height) {
   if (stride < 0 || width < 0 || height < 0)
     return false;
-  if (height > 0 && width > INT_MAX / height)
+  if (height > 0 && stride > INT_MAX / height)
     return false;
   return true;
 }
@@ -133,7 +133,7 @@
   return "";
 }
 
-std::vector<uint8_t> EncodePng(const uint8_t* buffer,
+std::vector<uint8_t> EncodePng(pdfium::span<const uint8_t> input,
                                int width,
                                int height,
                                int stride,
@@ -143,17 +143,17 @@
     case FPDFBitmap_Unknown:
       break;
     case FPDFBitmap_Gray:
-      png = image_diff_png::EncodeGrayPNG(buffer, width, height, stride);
+      png = image_diff_png::EncodeGrayPNG(input, width, height, stride);
       break;
     case FPDFBitmap_BGR:
-      png = image_diff_png::EncodeBGRPNG(buffer, width, height, stride);
+      png = image_diff_png::EncodeBGRPNG(input, width, height, stride);
       break;
     case FPDFBitmap_BGRx:
-      png = image_diff_png::EncodeBGRAPNG(buffer, width, height, stride,
+      png = image_diff_png::EncodeBGRAPNG(input, width, height, stride,
                                           /*discard_transparency=*/true);
       break;
     case FPDFBitmap_BGRA:
-      png = image_diff_png::EncodeBGRAPNG(buffer, width, height, stride,
+      png = image_diff_png::EncodeBGRAPNG(input, width, height, stride,
                                           /*discard_transparency=*/false);
       break;
     default:
@@ -383,9 +383,10 @@
   if (!CheckDimensions(stride, width, height))
     return "";
 
+  auto input =
+      pdfium::make_span(static_cast<uint8_t*>(buffer), stride * height);
   std::vector<uint8_t> png_encoding =
-      EncodePng(static_cast<const uint8_t*>(buffer), width, height, stride,
-                FPDFBitmap_BGRA);
+      EncodePng(input, width, height, stride, FPDFBitmap_BGRA);
   if (png_encoding.empty()) {
     fprintf(stderr, "Failed to convert bitmap to PNG\n");
     return "";
@@ -589,14 +590,17 @@
   if (format == FPDFBitmap_Unknown)
     return png_encoding;
 
-  const uint8_t* buffer =
-      static_cast<const uint8_t*>(FPDFBitmap_GetBuffer(bitmap.get()));
-
   int width = FPDFBitmap_GetWidth(bitmap.get());
   int height = FPDFBitmap_GetHeight(bitmap.get());
   int stride = FPDFBitmap_GetStride(bitmap.get());
+  if (!CheckDimensions(stride, width, height))
+    return png_encoding;
 
-  png_encoding = EncodePng(buffer, width, height, stride, format);
+  auto input = pdfium::make_span(
+      static_cast<const uint8_t*>(FPDFBitmap_GetBuffer(bitmap.get())),
+      stride * height);
+
+  png_encoding = EncodePng(input, width, height, stride, format);
   return png_encoding;
 }
 
diff --git a/testing/image_diff/image_diff.cpp b/testing/image_diff/image_diff.cpp
index d7abadf..a102a36 100644
--- a/testing/image_diff/image_diff.cpp
+++ b/testing/image_diff/image_diff.cpp
@@ -44,7 +44,7 @@
   bool has_image() const { return w_ > 0 && h_ > 0; }
   int w() const { return w_; }
   int h() const { return h_; }
-  const uint8_t* data() const { return &data_.front(); }
+  pdfium::span<const uint8_t> span() const { return data_; }
 
   // Creates the image from the given filename on disk, and returns true on
   // success.
@@ -296,7 +296,7 @@
     return kStatusSame;
 
   std::vector<uint8_t> png_encoding = image_diff_png::EncodeRGBAPNG(
-      diff_image.data(), diff_image.w(), diff_image.h(), diff_image.w() * 4);
+      diff_image.span(), diff_image.w(), diff_image.h(), diff_image.w() * 4);
   if (png_encoding.empty())
     return kStatusError;
 
diff --git a/testing/image_diff/image_diff_png.cpp b/testing/image_diff/image_diff_png.cpp
index 9b6e69b..dcd9d69 100644
--- a/testing/image_diff/image_diff_png.cpp
+++ b/testing/image_diff/image_diff_png.cpp
@@ -326,15 +326,14 @@
   png_info** pi_;
 };
 
-bool BuildPNGStruct(const uint8_t* input,
-                    size_t input_size,
+bool BuildPNGStruct(pdfium::span<const uint8_t> input,
                     png_struct** png_ptr,
                     png_info** info_ptr) {
-  if (input_size < 8)
+  if (input.size() < 8)
     return false;  // Input data too small to be a png
 
   // Have libpng check the signature, it likes the first 8 bytes.
-  if (png_sig_cmp(const_cast<uint8_t*>(input), 0, 8) != 0)
+  if (png_sig_cmp(const_cast<uint8_t*>(input.data()), 0, 8) != 0)
     return false;
 
   *png_ptr =
@@ -351,15 +350,14 @@
   return true;
 }
 
-std::vector<uint8_t> Decode(const uint8_t* input,
-                            size_t input_size,
+std::vector<uint8_t> Decode(pdfium::span<const uint8_t> input,
                             ColorFormat format,
                             int* w,
                             int* h) {
   std::vector<uint8_t> output;
   png_struct* png_ptr = nullptr;
   png_info* info_ptr = nullptr;
-  if (!BuildPNGStruct(input, input_size, &png_ptr, &info_ptr))
+  if (!BuildPNGStruct(input, &png_ptr, &info_ptr))
     return output;
 
   PngReadStructDestroyer destroyer(&png_ptr, &info_ptr);
@@ -374,7 +372,8 @@
 
   png_set_progressive_read_fn(png_ptr, &state, &DecodeInfoCallback,
                               &DecodeRowCallback, &DecodeEndCallback);
-  png_process_data(png_ptr, info_ptr, const_cast<uint8_t*>(input), input_size);
+  png_process_data(png_ptr, info_ptr, const_cast<uint8_t*>(input.data()),
+                   input.size());
 
   if (!state.done) {
     // Fed it all the data but the library didn't think we got all the data, so
@@ -495,7 +494,7 @@
                    int width,
                    int height,
                    int row_byte_width,
-                   const uint8_t* input,
+                   pdfium::span<const uint8_t> input,
                    int compression_level,
                    int png_output_color_type,
                    int output_color_components,
@@ -552,7 +551,7 @@
 }
 
 std::vector<uint8_t> EncodeWithCompressionLevel(
-    const uint8_t* input,
+    pdfium::span<const uint8_t> input,
     ColorFormat format,
     const int width,
     const int height,
@@ -643,7 +642,7 @@
   return output;
 }
 
-std::vector<uint8_t> Encode(const uint8_t* input,
+std::vector<uint8_t> Encode(pdfium::span<const uint8_t> input,
                             ColorFormat format,
                             const int width,
                             const int height,
@@ -662,10 +661,10 @@
                                int* width,
                                int* height) {
   ColorFormat format = reverse_byte_order ? FORMAT_BGRA : FORMAT_RGBA;
-  return Decode(input.data(), input.size(), format, width, height);
+  return Decode(input, format, width, height);
 }
 
-std::vector<uint8_t> EncodeBGRPNG(const uint8_t* input,
+std::vector<uint8_t> EncodeBGRPNG(pdfium::span<const uint8_t> input,
                                   int width,
                                   int height,
                                   int row_byte_width) {
@@ -673,7 +672,7 @@
                 std::vector<Comment>());
 }
 
-std::vector<uint8_t> EncodeRGBAPNG(const uint8_t* input,
+std::vector<uint8_t> EncodeRGBAPNG(pdfium::span<const uint8_t> input,
                                    int width,
                                    int height,
                                    int row_byte_width) {
@@ -681,7 +680,7 @@
                 std::vector<Comment>());
 }
 
-std::vector<uint8_t> EncodeBGRAPNG(const uint8_t* input,
+std::vector<uint8_t> EncodeBGRAPNG(pdfium::span<const uint8_t> input,
                                    int width,
                                    int height,
                                    int row_byte_width,
@@ -690,7 +689,7 @@
                 discard_transparency, std::vector<Comment>());
 }
 
-std::vector<uint8_t> EncodeGrayPNG(const uint8_t* input,
+std::vector<uint8_t> EncodeGrayPNG(pdfium::span<const uint8_t> input,
                                    int width,
                                    int height,
                                    int row_byte_width) {
diff --git a/testing/image_diff/image_diff_png.h b/testing/image_diff/image_diff_png.h
index 462003b..2c39bf0 100644
--- a/testing/image_diff/image_diff_png.h
+++ b/testing/image_diff/image_diff_png.h
@@ -21,26 +21,26 @@
                                int* height);
 
 // Encode a BGR pixel array into a PNG.
-std::vector<uint8_t> EncodeBGRPNG(const uint8_t* input,
+std::vector<uint8_t> EncodeBGRPNG(pdfium::span<const uint8_t> input,
                                   int width,
                                   int height,
                                   int row_byte_width);
 
 // Encode an RGBA pixel array into a PNG.
-std::vector<uint8_t> EncodeRGBAPNG(const uint8_t* input,
+std::vector<uint8_t> EncodeRGBAPNG(pdfium::span<const uint8_t> input,
                                    int width,
                                    int height,
                                    int row_byte_width);
 
 // Encode an BGRA pixel array into a PNG.
-std::vector<uint8_t> EncodeBGRAPNG(const uint8_t* input,
+std::vector<uint8_t> EncodeBGRAPNG(pdfium::span<const uint8_t> input,
                                    int width,
                                    int height,
                                    int row_byte_width,
                                    bool discard_transparency);
 
 // Encode a grayscale pixel array into a PNG.
-std::vector<uint8_t> EncodeGrayPNG(const uint8_t* input,
+std::vector<uint8_t> EncodeGrayPNG(pdfium::span<const uint8_t> input,
                                    int width,
                                    int height,
                                    int row_byte_width);
diff --git a/testing/utils/bitmap_saver.cpp b/testing/utils/bitmap_saver.cpp
index 7b7e475..524a9f6 100644
--- a/testing/utils/bitmap_saver.cpp
+++ b/testing/utils/bitmap_saver.cpp
@@ -7,6 +7,7 @@
 #include <fstream>
 #include <vector>
 
+#include "core/fxcrt/fx_safe_types.h"
 #include "testing/image_diff/image_diff_png.h"
 #include "third_party/base/logging.h"
 
@@ -16,14 +17,20 @@
   const int stride = FPDFBitmap_GetStride(bitmap);
   const int width = FPDFBitmap_GetWidth(bitmap);
   const int height = FPDFBitmap_GetHeight(bitmap);
-  const auto* buffer =
-      static_cast<const uint8_t*>(FPDFBitmap_GetBuffer(bitmap));
+  CHECK(stride >= 0);
+  CHECK(width >= 0);
+  CHECK(height >= 0);
+  FX_SAFE_FILESIZE size = stride;
+  size *= height;
+  auto input = pdfium::make_span(
+      static_cast<const uint8_t*>(FPDFBitmap_GetBuffer(bitmap)),
+      pdfium::base::ValueOrDieForType<size_t>(size));
 
   std::vector<uint8_t> png;
   if (FPDFBitmap_GetFormat(bitmap) == FPDFBitmap_Gray) {
-    png = image_diff_png::EncodeGrayPNG(buffer, width, height, stride);
+    png = image_diff_png::EncodeGrayPNG(input, width, height, stride);
   } else {
-    png = image_diff_png::EncodeBGRAPNG(buffer, width, height, stride,
+    png = image_diff_png::EncodeBGRAPNG(input, width, height, stride,
                                         /*discard_transparency=*/false);
   }