Only hash pixel data in EmbedderTest::HashBitmap().

Add a new EmbedderTest::HashBitmap() implementation that only hashes the
pixels in a given bitmap, and ignores the data in the gaps at the end of
rows. Per prior discussion on [1], the data in the gaps can in theory be
uninitialized. This does not most hashes, as most bitmaps in embedder
tests do not have gaps.

[1] https://pdfium-review.googlesource.com/64290

Change-Id: I24bd143f6b33c7ef86e26dd09d1cb874dea1675f
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/64331
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index cde8dd8..b96b679 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -3155,14 +3155,14 @@
   ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
   FPDF_BITMAP bitmap = FPDFImageObj_GetBitmap(obj);
   EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap));
-  CompareBitmap(bitmap, 109, 88, "0ab9295825313e00ad2534602c33785c");
+  CompareBitmap(bitmap, 109, 88, "cb3637934bb3b95a6e4ae1ea9eb9e56e");
   FPDFBitmap_Destroy(bitmap);
 
   obj = FPDFPage_GetObject(page, 34);
   ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
   bitmap = FPDFImageObj_GetBitmap(obj);
   EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap));
-  CompareBitmap(bitmap, 103, 75, "6317602bcc01385f38ad2f05291d0619");
+  CompareBitmap(bitmap, 103, 75, "c8d51fa6821ceb2a67f08446ff236c40");
   FPDFBitmap_Destroy(bitmap);
 
   obj = FPDFPage_GetObject(page, 35);
@@ -3176,21 +3176,21 @@
   ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
   bitmap = FPDFImageObj_GetBitmap(obj);
   EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap));
-  CompareBitmap(bitmap, 79, 60, "4c9cfa830a767038e6ec9b54e9e4b370");
+  CompareBitmap(bitmap, 79, 60, "f4e72fb783a01c7b4614cdc25eaa98ac");
   FPDFBitmap_Destroy(bitmap);
 
   obj = FPDFPage_GetObject(page, 37);
   ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
   bitmap = FPDFImageObj_GetBitmap(obj);
   EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap));
-  CompareBitmap(bitmap, 126, 106, "02c9a3b96f44a1430e03983d76b90921");
+  CompareBitmap(bitmap, 126, 106, "2cf9e66414c72461f4ccbf9cdebdfa1b");
   FPDFBitmap_Destroy(bitmap);
 
   obj = FPDFPage_GetObject(page, 38);
   ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
   bitmap = FPDFImageObj_GetBitmap(obj);
   EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap));
-  CompareBitmap(bitmap, 194, 119, "9df6ab21099ed1f202956f81e65450e5");
+  CompareBitmap(bitmap, 194, 119, "a8f3a126cec274dab8242fd2ccdc1b8b");
   FPDFBitmap_Destroy(bitmap);
   UnloadPage(page);
 }
diff --git a/fpdfsdk/fpdf_thumbnail_embeddertest.cpp b/fpdfsdk/fpdf_thumbnail_embeddertest.cpp
index c99bf9d..101e1e4 100644
--- a/fpdfsdk/fpdf_thumbnail_embeddertest.cpp
+++ b/fpdfsdk/fpdf_thumbnail_embeddertest.cpp
@@ -184,7 +184,7 @@
     EXPECT_EQ(50, FPDFBitmap_GetHeight(thumb_bitmap.get()));
     EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(thumb_bitmap.get()));
     CompareBitmap(thumb_bitmap.get(), 50, 50,
-                  "73c43ed7cffd23de2408857a96bbdde8");
+                  "52b75451e396f55e95d1cb68e6018226");
 
     UnloadPage(page);
   }
@@ -199,7 +199,7 @@
     EXPECT_EQ(50, FPDFBitmap_GetHeight(thumb_bitmap.get()));
     EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(thumb_bitmap.get()));
     CompareBitmap(thumb_bitmap.get(), 50, 50,
-                  "d7d906ebee289d0ac07ef11842d9f779");
+                  "1f448be08c6e6043ccd0bad8ecc2a351");
 
     UnloadPage(page);
   }
@@ -243,7 +243,7 @@
   EXPECT_EQ(10, FPDFBitmap_GetWidth(thumb_bitmap.get()));
   EXPECT_EQ(10, FPDFBitmap_GetHeight(thumb_bitmap.get()));
   EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(thumb_bitmap.get()));
-  CompareBitmap(thumb_bitmap.get(), 10, 10, "91ca98dbff38b9a50f8c1dfc621ff79f");
+  CompareBitmap(thumb_bitmap.get(), 10, 10, "fe02583f9e6d094042a942ff686e9936");
 
   UnloadPage(page);
 }
@@ -273,7 +273,7 @@
   EXPECT_EQ(50, FPDFBitmap_GetWidth(thumb_bitmap.get()));
   EXPECT_EQ(50, FPDFBitmap_GetHeight(thumb_bitmap.get()));
   EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(thumb_bitmap.get()));
-  CompareBitmap(thumb_bitmap.get(), 50, 50, "73c43ed7cffd23de2408857a96bbdde8");
+  CompareBitmap(thumb_bitmap.get(), 50, 50, "52b75451e396f55e95d1cb68e6018226");
 
   // Get the raw data again
   unsigned long new_raw_size = FPDFPage_GetRawThumbnailData(page, nullptr, 0);
diff --git a/testing/embedder_test.cpp b/testing/embedder_test.cpp
index 2cdfb55..7a52d25 100644
--- a/testing/embedder_test.cpp
+++ b/testing/embedder_test.cpp
@@ -603,10 +603,18 @@
 
 // static
 std::string EmbedderTest::HashBitmap(FPDF_BITMAP bitmap) {
+  int stride = FPDFBitmap_GetStride(bitmap);
+  int usable_bytes_per_row =
+      GetBitmapBytesPerPixel(bitmap) * FPDFBitmap_GetWidth(bitmap);
+  int height = FPDFBitmap_GetHeight(bitmap);
+  auto span = pdfium::make_span(
+      static_cast<uint8_t*>(FPDFBitmap_GetBuffer(bitmap)), stride * height);
+
+  CRYPT_md5_context context = CRYPT_MD5Start();
+  for (int i = 0; i < height; ++i)
+    CRYPT_MD5Update(&context, span.subspan(i * stride, usable_bytes_per_row));
   uint8_t digest[16];
-  size_t size = FPDFBitmap_GetStride(bitmap) * FPDFBitmap_GetHeight(bitmap);
-  CRYPT_MD5Generate({static_cast<uint8_t*>(FPDFBitmap_GetBuffer(bitmap)), size},
-                    digest);
+  CRYPT_MD5Finish(&context, digest);
   return CryptToBase16(digest);
 }
 
diff --git a/testing/embedder_test.h b/testing/embedder_test.h
index 5896d8a..f33a955 100644
--- a/testing/embedder_test.h
+++ b/testing/embedder_test.h
@@ -191,7 +191,8 @@
   FPDF_FORMHANDLE SetupFormFillEnvironment(FPDF_DOCUMENT doc,
                                            JavaScriptOption javascript_option);
 
-  // Return the hash of |bitmap|.
+  // Return the hash of only the pixels in |bitmap|. i.e. Excluding the gap, if
+  // any, at the end of a row where the stride is larger than width * bpp.
   static std::string HashBitmap(FPDF_BITMAP bitmap);
 
 #ifndef NDEBUG