[M90-LTS] Use more safe arithmetic in CFX_DIBBase

Most of the calculations are "safe" because we know that the DIB
has validated sizes before allocating a buffer, and that calculations
in terms of bytes won't overflow and will be within the buffer. But
calculations in terms of bits might create overflow in temporaries,
so use safe arithmetic there instead.

Re-arranging the order of operations thus converting to bytes first
might be one option, but we want to handle the 1 bpp case.

Test would require large images that might not be possible on
all platforms.

M90 merge issues:
  cfx_bitmapcomposer.cpp: conflicting includes, and conflicting
  declaration of dest_scan

Bug: chromium:1253399
Change-Id: I3c6c5b8b1f1bf3f429c7d377a8a84c5ab53cafd9
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/85510
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
(cherry picked from commit a8b293732a0160d1bc1d5b0ad5744922f0f820d5)
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/86230
diff --git a/core/fxge/dib/cfx_bitmapcomposer.cpp b/core/fxge/dib/cfx_bitmapcomposer.cpp
index 86066ba..af7a248 100644
--- a/core/fxge/dib/cfx_bitmapcomposer.cpp
+++ b/core/fxge/dib/cfx_bitmapcomposer.cpp
@@ -6,6 +6,7 @@
 
 #include "core/fxge/dib/cfx_bitmapcomposer.h"
 
+#include "core/fxcrt/fx_safe_types.h"
 #include "core/fxge/cfx_cliprgn.h"
 #include "core/fxge/dib/cfx_dibitmap.h"
 
@@ -109,8 +110,17 @@
                     m_pClipMask->GetPitch() +
                 (m_DestLeft - m_pClipRgn->GetBox().left);
   }
-  uint8_t* dest_scan = m_pBitmap->GetWritableScanline(line + m_DestTop) +
-                       m_DestLeft * m_pBitmap->GetBPP() / 8;
+  uint8_t* dest_scan = m_pBitmap->GetWritableScanline(line + m_DestTop);
+  if (dest_scan) {
+    FX_SAFE_UINT32 offset = m_DestLeft;
+    offset *= m_pBitmap->GetBPP();
+    offset /= 8;
+    if (!offset.IsValid())
+      return;
+
+    // Help some compilers perform pointer arithmetic against safe numerics.
+    dest_scan += static_cast<uint32_t>(offset.ValueOrDie());
+  }
   uint8_t* dest_alpha_scan =
       m_pBitmap->m_pAlphaMask
           ? m_pBitmap->m_pAlphaMask->GetWritableScanline(line + m_DestTop) +
diff --git a/core/fxge/dib/cfx_dibbase.cpp b/core/fxge/dib/cfx_dibbase.cpp
index 137556e..e0186e5 100644
--- a/core/fxge/dib/cfx_dibbase.cpp
+++ b/core/fxge/dib/cfx_dibbase.cpp
@@ -628,15 +628,25 @@
       }
     }
   } else {
-    int copy_len = (pNewBitmap->GetWidth() * pNewBitmap->GetBPP() + 7) / 8;
-    if (m_Pitch < static_cast<uint32_t>(copy_len))
-      copy_len = m_Pitch;
+    FX_SAFE_UINT32 copy_len = pNewBitmap->GetWidth();
+    copy_len *= pNewBitmap->GetBPP();
+    copy_len += 7;
+    copy_len /= 8;
+    if (!copy_len.IsValid())
+      return nullptr;
+
+    copy_len = std::min<uint32_t>(m_Pitch, copy_len.ValueOrDie());
+
+    FX_SAFE_UINT32 offset = rect.left;
+    offset *= GetBppFromFormat(m_Format);
+    offset /= 8;
+    if (!offset.IsValid())
+      return nullptr;
 
     for (int row = rect.top; row < rect.bottom; ++row) {
-      const uint8_t* src_scan =
-          GetScanline(row) + rect.left * GetBppFromFormat(m_Format) / 8;
+      const uint8_t* src_scan = GetScanline(row) + offset.ValueOrDie();
       uint8_t* dest_scan = pNewBitmap->GetWritableScanline(row - rect.top);
-      memcpy(dest_scan, src_scan, copy_len);
+      memcpy(dest_scan, src_scan, copy_len.ValueOrDie());
     }
   }
   return pNewBitmap;
diff --git a/core/fxge/dib/cfx_dibitmap.cpp b/core/fxge/dib/cfx_dibitmap.cpp
index 5012d44..ad23d4b 100644
--- a/core/fxge/dib/cfx_dibitmap.cpp
+++ b/core/fxge/dib/cfx_dibitmap.cpp
@@ -216,8 +216,14 @@
   if (GetBppFromFormat(m_Format) == 8)
     dest_format = FXDIB_Format::k8bppMask;
 
+  FX_SAFE_UINT32 offset = dest_left;
+  offset *= GetBPP();
+  offset /= 8;
+  if (!offset.IsValid())
+    return false;
+
   uint8_t* dest_buf =
-      m_pBuffer.Get() + dest_top * m_Pitch + dest_left * GetBPP() / 8;
+      m_pBuffer.Get() + dest_top * m_Pitch + offset.ValueOrDie();
   std::vector<uint32_t, FxAllocAllocator<uint32_t>> d_plt;
   return ConvertBuffer(dest_format, dest_buf, m_Pitch, width, height,
                        pSrcBitmap, src_left, src_top, &d_plt);
@@ -497,7 +503,13 @@
   if (!m_pBuffer)
     return 0;
 
-  uint8_t* pos = m_pBuffer.Get() + y * m_Pitch + x * GetBPP() / 8;
+  FX_SAFE_UINT32 offset = x;
+  offset *= GetBPP();
+  offset /= 8;
+  if (!offset.IsValid())
+    return 0;
+
+  uint8_t* pos = m_pBuffer.Get() + y * m_Pitch + offset.ValueOrDie();
   switch (GetFormat()) {
     case FXDIB_Format::k1bppMask: {
       if ((*pos) & (1 << (7 - x % 8))) {
@@ -536,7 +548,13 @@
   if (x < 0 || x >= m_Width || y < 0 || y >= m_Height)
     return;
 
-  uint8_t* pos = m_pBuffer.Get() + y * m_Pitch + x * GetBPP() / 8;
+  FX_SAFE_UINT32 offset = x;
+  offset *= GetBPP();
+  offset /= 8;
+  if (!offset.IsValid())
+    return;
+
+  uint8_t* pos = m_pBuffer.Get() + y * m_Pitch + offset.ValueOrDie();
   switch (GetFormat()) {
     case FXDIB_Format::k1bppMask:
       if (color >> 24) {