Return span<> from CFX_DIBBase::GetBuffer().

This is complicated by the fact that the DIB doesn't really
track the size of the buffer it is given, but assume the
callers gave us a sufficient one.

-- Invoke .data() in many callees to keep patch size small.

Change-Id: I5d9034eda28f222f78af4c7f0188fa4e21781d82
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/100910
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_dib.cpp b/core/fpdfapi/page/cpdf_dib.cpp
index a8d1c84..00f5bfd 100644
--- a/core/fpdfapi/page/cpdf_dib.cpp
+++ b/core/fpdfapi/page/cpdf_dib.cpp
@@ -294,7 +294,8 @@
     iDecodeStatus = Jbig2Decoder::StartDecode(
         m_pJbig2Context.get(), m_pDocument->GetOrCreateCodecContext(), m_Width,
         m_Height, pSrcSpan, nSrcKey, pGlobalSpan, nGlobalKey,
-        m_pCachedBitmap->GetBuffer(), m_pCachedBitmap->GetPitch(), pPause);
+        m_pCachedBitmap->GetBuffer().data(), m_pCachedBitmap->GetPitch(),
+        pPause);
   } else {
     iDecodeStatus = Jbig2Decoder::ContinueDecode(m_pJbig2Context.get(), pPause);
   }
@@ -645,8 +646,8 @@
     return nullptr;
 
   result_bitmap->Clear(0xFFFFFFFF);
-  if (!decoder->Decode(result_bitmap->GetBuffer(), result_bitmap->GetPitch(),
-                       swap_rgb)) {
+  if (!decoder->Decode(result_bitmap->GetBuffer().data(),
+                       result_bitmap->GetPitch(), swap_rgb)) {
     return nullptr;
   }
 
@@ -1057,8 +1058,9 @@
   return true;
 }
 
-uint8_t* CPDF_DIB::GetBuffer() const {
-  return m_pCachedBitmap ? m_pCachedBitmap->GetBuffer() : nullptr;
+pdfium::span<uint8_t> CPDF_DIB::GetBuffer() const {
+  return m_pCachedBitmap ? m_pCachedBitmap->GetBuffer()
+                         : pdfium::span<uint8_t>();
 }
 
 pdfium::span<const uint8_t> CPDF_DIB::GetScanline(int line) const {
diff --git a/core/fpdfapi/page/cpdf_dib.h b/core/fpdfapi/page/cpdf_dib.h
index ecf7782..297f0aa 100644
--- a/core/fpdfapi/page/cpdf_dib.h
+++ b/core/fpdfapi/page/cpdf_dib.h
@@ -45,7 +45,7 @@
   CONSTRUCT_VIA_MAKE_RETAIN;
 
   // CFX_DIBBase:
-  uint8_t* GetBuffer() const override;
+  pdfium::span<uint8_t> GetBuffer() const override;
   pdfium::span<const uint8_t> GetScanline(int line) const override;
   bool SkipToScanline(int line, PauseIndicatorIface* pPause) const override;
   size_t GetEstimatedImageMemoryBurden() const override;
diff --git a/core/fpdfapi/page/cpdf_image.cpp b/core/fpdfapi/page/cpdf_image.cpp
index f5e4971..718abe8 100644
--- a/core/fpdfapi/page/cpdf_image.cpp
+++ b/core/fpdfapi/page/cpdf_image.cpp
@@ -293,7 +293,7 @@
                                      pNewStream->GetObjNum());
   }
 
-  uint8_t* src_buf = pBitmap->GetBuffer();
+  uint8_t* src_buf = pBitmap->GetBuffer().data();
   int32_t src_pitch = pBitmap->GetPitch();
   DataVector<uint8_t> dest_buf(Fx2DSizeOrDie(dest_pitch, BitmapHeight));
   auto dest_span = pdfium::make_span(dest_buf);
diff --git a/core/fpdfapi/render/cpdf_rendershading.cpp b/core/fpdfapi/render/cpdf_rendershading.cpp
index e2fe6fc..5228a70 100644
--- a/core/fpdfapi/render/cpdf_rendershading.cpp
+++ b/core/fpdfapi/render/cpdf_rendershading.cpp
@@ -918,7 +918,7 @@
     return;
 
   RetainPtr<CFX_DIBitmap> pBitmap = buffer.GetBitmap();
-  if (!pBitmap->GetBuffer())
+  if (pBitmap->GetBuffer().empty())
     return;
 
   pBitmap->Clear(background);
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index f696ade..bd8c149 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -769,7 +769,7 @@
   else
     m_pDevice->CreateCompatibleBitmap(pBackdrop, width, height);
 
-  if (!pBackdrop->GetBuffer())
+  if (pBackdrop->GetBuffer().empty())
     return nullptr;
 
   bool bNeedDraw;
@@ -1444,9 +1444,9 @@
   if (!pMask->Create(width, height, FXDIB_Format::k8bppMask))
     return nullptr;
 
-  uint8_t* dest_buf = pMask->GetBuffer();
+  uint8_t* dest_buf = pMask->GetBuffer().data();
   int dest_pitch = pMask->GetPitch();
-  uint8_t* src_buf = bitmap->GetBuffer();
+  uint8_t* src_buf = bitmap->GetBuffer().data();
   int src_pitch = bitmap->GetPitch();
   DataVector<uint8_t> transfers(256);
   if (pFunc) {
diff --git a/core/fpdfapi/render/cpdf_rendertiling.cpp b/core/fpdfapi/render/cpdf_rendertiling.cpp
index 1d24b81..8a48e24 100644
--- a/core/fpdfapi/render/cpdf_rendertiling.cpp
+++ b/core/fpdfapi/render/cpdf_rendertiling.cpp
@@ -197,7 +197,7 @@
     return nullptr;
 
   pScreen->Clear(0);
-  const uint8_t* const src_buf = pPatternBitmap->GetBuffer();
+  pdfium::span<const uint8_t> src_buf = pPatternBitmap->GetBuffer();
   for (int col = min_col; col <= max_col; col++) {
     for (int row = min_row; row <= max_row; row++) {
       int start_x;
@@ -230,10 +230,11 @@
         uint32_t* dest_buf = reinterpret_cast<uint32_t*>(
             pScreen->GetWritableScanline(start_y).subspan(start_x * 4).data());
         if (pPattern->colored()) {
-          const auto* src_buf32 = reinterpret_cast<const uint32_t*>(src_buf);
+          const auto* src_buf32 =
+              reinterpret_cast<const uint32_t*>(src_buf.data());
           *dest_buf = *src_buf32;
         } else {
-          *dest_buf = (*src_buf << 24) | (fill_argb & 0xffffff);
+          *dest_buf = (*(src_buf.data()) << 24) | (fill_argb & 0xffffff);
         }
       } else {
         if (pPattern->colored()) {
diff --git a/core/fxcodec/progressive_decoder.cpp b/core/fxcodec/progressive_decoder.cpp
index e9db8c4..3c1f6a4 100644
--- a/core/fxcodec/progressive_decoder.cpp
+++ b/core/fxcodec/progressive_decoder.cpp
@@ -1285,7 +1285,7 @@
 
   auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
   pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Format::kArgb);
-  if (!pDIBitmap->GetBuffer()) {
+  if (pDIBitmap->GetBuffer().empty()) {
     m_pDeviceBitmap = nullptr;
     m_pFile = nullptr;
     m_status = FXCODEC_STATUS::kError;
diff --git a/core/fxcodec/tiff/tiff_decoder.cpp b/core/fxcodec/tiff/tiff_decoder.cpp
index 7451fbe..ca79376 100644
--- a/core/fxcodec/tiff/tiff_decoder.cpp
+++ b/core/fxcodec/tiff/tiff_decoder.cpp
@@ -428,8 +428,8 @@
     uint16_t rotation = ORIENTATION_TOPLEFT;
     TIFFGetField(m_tif_ctx.get(), TIFFTAG_ORIENTATION, &rotation);
     if (TIFFReadRGBAImageOriented(m_tif_ctx.get(), img_width, img_height,
-                                  (uint32*)pDIBitmap->GetBuffer(), rotation,
-                                  1)) {
+                                  (uint32*)pDIBitmap->GetBuffer().data(),
+                                  rotation, 1)) {
       for (uint32_t row = 0; row < img_height; row++) {
         uint8_t* row_buf = pDIBitmap->GetWritableScanline(row).data();
         TiffBGRA2RGBA(row_buf, img_width, 4);
diff --git a/core/fxge/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp
index 4d5b6aa..1346ee7 100644
--- a/core/fxge/agg/fx_agg_driver.cpp
+++ b/core/fxge/agg/fx_agg_driver.cpp
@@ -71,7 +71,7 @@
   int src_b = FXARGB_B(argb);
   int Bpp = pBitmap->GetBPP() / 8;
   int dib_argb = FXARGB_TOBGRORDERDIB(argb);
-  uint8_t* pBuffer = pBitmap->GetBuffer();
+  uint8_t* pBuffer = pBitmap->GetBuffer().data();
   if (src_alpha == 255) {
     for (int row = rect.top; row < rect.bottom; row++) {
       uint8_t* dest_scan =
@@ -146,7 +146,7 @@
   FXDIB_Format dest_format = pBitmap->GetFormat();
   FXDIB_Format src_format = pSrcBitmap->GetFormat();
   int pitch = pBitmap->GetPitch();
-  uint8_t* buffer = pBitmap->GetBuffer();
+  uint8_t* buffer = pBitmap->GetBuffer().data();
   if (dest_format == src_format) {
     for (int row = 0; row < height; row++) {
       uint8_t* dest_scan = buffer + (dest_top + row) * pitch + dest_left * Bpp;
@@ -844,17 +844,19 @@
   if (y < m_ClipBox.top || y >= m_ClipBox.bottom)
     return;
 
-  uint8_t* dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * y;
+  uint8_t* dest_scan =
+      m_pDevice->GetBuffer().subspan(m_pDevice->GetPitch() * y).data();
   uint8_t* dest_scan_extra_alpha = nullptr;
   RetainPtr<CFX_DIBitmap> pAlphaMask = m_pDevice->GetAlphaMask();
   if (pAlphaMask) {
     dest_scan_extra_alpha =
-        pAlphaMask->GetBuffer() + pAlphaMask->GetPitch() * y;
+        pAlphaMask->GetBuffer().subspan(pAlphaMask->GetPitch() * y).data();
   }
   uint8_t* backdrop_scan = nullptr;
   if (m_pBackdropDevice) {
-    backdrop_scan =
-        m_pBackdropDevice->GetBuffer() + m_pBackdropDevice->GetPitch() * y;
+    backdrop_scan = m_pBackdropDevice->GetBuffer()
+                        .subspan(m_pBackdropDevice->GetPitch() * y)
+                        .data();
   }
   int Bpp = m_pDevice->GetBPP() / 8;
   bool bDestAlpha = m_pDevice->IsAlphaFormat() || m_pDevice->IsMaskFormat();
@@ -879,7 +881,8 @@
     }
     uint8_t* clip_pos = nullptr;
     if (m_pClipMask) {
-      clip_pos = m_pClipMask->GetBuffer() +
+      // TODO(crbug.com/1382604): use subspan arithmetic.
+      clip_pos = m_pClipMask->GetBuffer().data() +
                  (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x -
                  m_ClipBox.left;
     }
@@ -1109,8 +1112,8 @@
   pThisLayer->Create(path_rect.Width(), path_rect.Height(),
                      FXDIB_Format::k8bppMask);
   pThisLayer->Clear(0);
-  agg::rendering_buffer raw_buf(pThisLayer->GetBuffer(), pThisLayer->GetWidth(),
-                                pThisLayer->GetHeight(),
+  agg::rendering_buffer raw_buf(pThisLayer->GetBuffer().data(),
+                                pThisLayer->GetWidth(), pThisLayer->GetHeight(),
                                 pThisLayer->GetPitch());
   agg::pixfmt_gray8 pixel_buf(raw_buf);
   agg::renderer_base<agg::pixfmt_gray8> base_buf(pixel_buf);
@@ -1204,7 +1207,7 @@
   if (blend_type != BlendMode::kNormal)
     return false;
 
-  if (!m_pBitmap->GetBuffer())
+  if (m_pBitmap->GetBuffer().empty())
     return true;
 
   m_FillOptions = fill_options;
@@ -1266,7 +1269,7 @@
   if (blend_type != BlendMode::kNormal)
     return false;
 
-  if (!m_pBitmap->GetBuffer())
+  if (m_pBitmap->GetBuffer().empty())
     return true;
 
   FX_RECT clip_rect;
@@ -1309,7 +1312,7 @@
 bool CFX_AggDeviceDriver::GetDIBits(const RetainPtr<CFX_DIBitmap>& pBitmap,
                                     int left,
                                     int top) {
-  if (!m_pBitmap->GetBuffer())
+  if (m_pBitmap->GetBuffer().empty())
     return true;
 
   FX_RECT rect(left, top, left + pBitmap->GetWidth(),
@@ -1349,7 +1352,7 @@
                                     int left,
                                     int top,
                                     BlendMode blend_type) {
-  if (!m_pBitmap->GetBuffer())
+  if (m_pBitmap->GetBuffer().empty())
     return true;
 
   if (pBitmap->IsMaskFormat()) {
@@ -1372,7 +1375,7 @@
                                         const FX_RECT* pClipRect,
                                         const FXDIB_ResampleOptions& options,
                                         BlendMode blend_type) {
-  if (!m_pBitmap->GetBuffer())
+  if (m_pBitmap->GetBuffer().empty())
     return true;
 
   if (dest_width == pSource->GetWidth() &&
@@ -1404,7 +1407,7 @@
     const FXDIB_ResampleOptions& options,
     std::unique_ptr<CFX_ImageRenderer>* handle,
     BlendMode blend_type) {
-  if (!m_pBitmap->GetBuffer())
+  if (m_pBitmap->GetBuffer().empty())
     return true;
 
   *handle = std::make_unique<CFX_ImageRenderer>(
@@ -1415,7 +1418,7 @@
 
 bool CFX_AggDeviceDriver::ContinueDIBits(CFX_ImageRenderer* pHandle,
                                          PauseIndicatorIface* pPause) {
-  return !m_pBitmap->GetBuffer() || pHandle->Continue(pPause);
+  return m_pBitmap->GetBuffer().empty() || pHandle->Continue(pPause);
 }
 
 }  // namespace pdfium
diff --git a/core/fxge/apple/fx_apple_impl.cpp b/core/fxge/apple/fx_apple_impl.cpp
index b9b5ed7..c1649a2 100644
--- a/core/fxge/apple/fx_apple_impl.cpp
+++ b/core/fxge/apple/fx_apple_impl.cpp
@@ -134,7 +134,7 @@
     RetainPtr<CFX_DIBitmap> pClipMask = m_pClipRgn->GetMask();
     if (pClipMask) {
       CGDataProviderRef pClipMaskDataProvider = CGDataProviderCreateWithData(
-          nullptr, pClipMask->GetBuffer(),
+          nullptr, pClipMask->GetBuffer().data(),
           pClipMask->GetPitch() * pClipMask->GetHeight(), DoNothing);
       CGFloat decode_f[2] = {255.f, 0.f};
       pImageCG = CGImageMaskCreate(
diff --git a/core/fxge/apple/fx_quartz_device.cpp b/core/fxge/apple/fx_quartz_device.cpp
index eea84cb..9f5f13f 100644
--- a/core/fxge/apple/fx_quartz_device.cpp
+++ b/core/fxge/apple/fx_quartz_device.cpp
@@ -33,7 +33,7 @@
   }
   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   CGContextRef context = CGBitmapContextCreate(
-      pBitmap->GetBuffer(), pBitmap->GetWidth(), pBitmap->GetHeight(), 8,
+      pBitmap->GetBuffer().data(), pBitmap->GetWidth(), pBitmap->GetHeight(), 8,
       pBitmap->GetPitch(), colorSpace, bmpInfo);
   CGColorSpaceRelease(colorSpace);
   return context;
diff --git a/core/fxge/cfx_glyphcache.cpp b/core/fxge/cfx_glyphcache.cpp
index 970783e..4c783fb 100644
--- a/core/fxge/cfx_glyphcache.cpp
+++ b/core/fxge/cfx_glyphcache.cpp
@@ -198,7 +198,7 @@
                                         : FXDIB_Format::k8bppMask);
   int dest_pitch = pGlyphBitmap->GetBitmap()->GetPitch();
   int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(GetFaceRec()));
-  uint8_t* pDestBuf = pGlyphBitmap->GetBitmap()->GetBuffer();
+  uint8_t* pDestBuf = pGlyphBitmap->GetBitmap()->GetBuffer().data();
   uint8_t* pSrcBuf = static_cast<uint8_t*>(
       FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(GetFaceRec())));
   if (anti_alias != FT_RENDER_MODE_MONO &&
diff --git a/core/fxge/dib/cfx_bitmapcomposer.cpp b/core/fxge/dib/cfx_bitmapcomposer.cpp
index 3245005..d083ca3 100644
--- a/core/fxge/dib/cfx_bitmapcomposer.cpp
+++ b/core/fxge/dib/cfx_bitmapcomposer.cpp
@@ -141,13 +141,13 @@
   int dest_pitch = m_pBitmap->GetPitch();
   int dest_alpha_pitch = m_pBitmap->GetAlphaMaskPitch();
   int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line);
-  uint8_t* dest_buf = m_pBitmap->GetBuffer();
+  uint8_t* dest_buf = m_pBitmap->GetBuffer().data();
   if (dest_buf) {
     dest_buf += dest_x * Bpp + m_DestTop * dest_pitch;
     if (m_bFlipY)
       dest_buf += dest_pitch * (m_DestHeight - 1);
   }
-  uint8_t* dest_alpha_buf = m_pBitmap->GetAlphaMaskBuffer();
+  uint8_t* dest_alpha_buf = m_pBitmap->GetAlphaMaskBuffer().data();
   if (dest_alpha_buf) {
     dest_alpha_buf += dest_x + m_DestTop * dest_alpha_pitch;
     if (m_bFlipY)
diff --git a/core/fxge/dib/cfx_dibbase.cpp b/core/fxge/dib/cfx_dibbase.cpp
index 7562517..3842307 100644
--- a/core/fxge/dib/cfx_dibbase.cpp
+++ b/core/fxge/dib/cfx_dibbase.cpp
@@ -607,8 +607,8 @@
 
 CFX_DIBBase::~CFX_DIBBase() = default;
 
-uint8_t* CFX_DIBBase::GetBuffer() const {
-  return nullptr;
+pdfium::span<uint8_t> CFX_DIBBase::GetBuffer() const {
+  return pdfium::span<uint8_t>();
 }
 
 bool CFX_DIBBase::SkipToScanline(int line, PauseIndicatorIface* pPause) const {
@@ -880,8 +880,8 @@
                       : pdfium::span<uint8_t>();
 }
 
-uint8_t* CFX_DIBBase::GetAlphaMaskBuffer() {
-  return m_pAlphaMask ? m_pAlphaMask->GetBuffer() : nullptr;
+pdfium::span<uint8_t> CFX_DIBBase::GetAlphaMaskBuffer() {
+  return m_pAlphaMask ? m_pAlphaMask->GetBuffer() : pdfium::span<uint8_t>();
 }
 
 RetainPtr<CFX_DIBitmap> CFX_DIBBase::GetAlphaMask() {
@@ -1037,8 +1037,9 @@
 
   RetainPtr<const CFX_DIBBase> holder(this);
   DataVector<uint32_t> pal_8bpp;
-  if (!ConvertBuffer(dest_format, pClone->GetBuffer(), pClone->GetPitch(),
-                     m_Width, m_Height, holder, 0, 0, &pal_8bpp)) {
+  if (!ConvertBuffer(dest_format, pClone->GetBuffer().data(),
+                     pClone->GetPitch(), m_Width, m_Height, holder, 0, 0,
+                     &pal_8bpp)) {
     return nullptr;
   }
   if (!pal_8bpp.empty())
@@ -1060,7 +1061,7 @@
 
   pTransBitmap->SetPalette(GetPaletteSpan());
   int dest_pitch = pTransBitmap->GetPitch();
-  uint8_t* dest_buf = pTransBitmap->GetBuffer();
+  uint8_t* dest_buf = pTransBitmap->GetBuffer().data();
   int row_start = bXFlip ? m_Height - dest_clip.right : dest_clip.left;
   int row_end = bXFlip ? m_Height - dest_clip.left : dest_clip.right;
   int col_start = bYFlip ? m_Width - dest_clip.bottom : dest_clip.top;
@@ -1121,7 +1122,7 @@
   }
   if (m_pAlphaMask) {
     dest_pitch = pTransBitmap->m_pAlphaMask->GetPitch();
-    dest_buf = pTransBitmap->m_pAlphaMask->GetBuffer();
+    dest_buf = pTransBitmap->m_pAlphaMask->GetBuffer().data();
     int dest_step = bYFlip ? -dest_pitch : dest_pitch;
     for (int row = row_start; row < row_end; ++row) {
       int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) -
diff --git a/core/fxge/dib/cfx_dibbase.h b/core/fxge/dib/cfx_dibbase.h
index 293f6c8..780322a 100644
--- a/core/fxge/dib/cfx_dibbase.h
+++ b/core/fxge/dib/cfx_dibbase.h
@@ -34,7 +34,7 @@
 
   ~CFX_DIBBase() override;
 
-  virtual uint8_t* GetBuffer() const;
+  virtual pdfium::span<uint8_t> GetBuffer() const;
   virtual pdfium::span<const uint8_t> GetScanline(int line) const = 0;
   virtual bool SkipToScanline(int line, PauseIndicatorIface* pPause) const;
   virtual size_t GetEstimatedImageMemoryBurden() const;
@@ -79,7 +79,7 @@
   uint32_t GetAlphaMaskPitch() const;
   pdfium::span<const uint8_t> GetAlphaMaskScanline(int line) const;
   pdfium::span<uint8_t> GetWritableAlphaMaskScanline(int line);
-  uint8_t* GetAlphaMaskBuffer();
+  pdfium::span<uint8_t> GetAlphaMaskBuffer();
   RetainPtr<CFX_DIBitmap> GetAlphaMask();
   RetainPtr<CFX_DIBitmap> CloneAlphaMask() const;
 
diff --git a/core/fxge/dib/cfx_dibextractor.cpp b/core/fxge/dib/cfx_dibextractor.cpp
index 494483d..582d933 100644
--- a/core/fxge/dib/cfx_dibextractor.cpp
+++ b/core/fxge/dib/cfx_dibextractor.cpp
@@ -10,14 +10,15 @@
 #include "core/fxge/dib/cfx_dibitmap.h"
 
 CFX_DIBExtractor::CFX_DIBExtractor(const RetainPtr<CFX_DIBBase>& pSrc) {
-  if (!pSrc->GetBuffer()) {
+  if (pSrc->GetBuffer().empty()) {
     m_pBitmap = pSrc->Realize();
     return;
   }
   RetainPtr<CFX_DIBBase> pOldSrc(pSrc);
   m_pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
   if (!m_pBitmap->Create(pOldSrc->GetWidth(), pOldSrc->GetHeight(),
-                         pOldSrc->GetFormat(), pOldSrc->GetBuffer(), 0)) {
+                         pOldSrc->GetFormat(), pOldSrc->GetBuffer().data(),
+                         0)) {
     m_pBitmap.Reset();
     return;
   }
diff --git a/core/fxge/dib/cfx_dibitmap.cpp b/core/fxge/dib/cfx_dibitmap.cpp
index ebd6ba8..ae82b30 100644
--- a/core/fxge/dib/cfx_dibitmap.cpp
+++ b/core/fxge/dib/cfx_dibitmap.cpp
@@ -17,6 +17,7 @@
 #include "core/fxcrt/data_vector.h"
 #include "core/fxcrt/fx_coordinates.h"
 #include "core/fxcrt/fx_safe_types.h"
+#include "core/fxcrt/span_util.h"
 #include "core/fxge/calculate_pitch.h"
 #include "core/fxge/cfx_cliprgn.h"
 #include "core/fxge/cfx_defaultrenderdevice.h"
@@ -98,20 +99,24 @@
 
 CFX_DIBitmap::~CFX_DIBitmap() = default;
 
-uint8_t* CFX_DIBitmap::GetBuffer() const {
-  return m_pBuffer.Get();
+pdfium::span<uint8_t> CFX_DIBitmap::GetBuffer() const {
+  if (!m_pBuffer)
+    return pdfium::span<uint8_t>();
+
+  return {m_pBuffer.Get(), m_Height * m_Pitch};
 }
 
 pdfium::span<const uint8_t> CFX_DIBitmap::GetScanline(int line) const {
-  if (!m_pBuffer)
+  auto buffer_span = GetBuffer();
+  if (buffer_span.empty())
     return pdfium::span<const uint8_t>();
 
-  return {m_pBuffer.Get() + line * m_Pitch, m_Pitch};
+  return buffer_span.subspan(line * m_Pitch, m_Pitch);
 }
 
 size_t CFX_DIBitmap::GetEstimatedImageMemoryBurden() const {
   size_t result = CFX_DIBBase::GetEstimatedImageMemoryBurden();
-  if (GetBuffer()) {
+  if (!GetBuffer().empty()) {
     int height = GetHeight();
     CHECK(pdfium::base::IsValueInRangeForNumericType<size_t>(height));
     result += static_cast<size_t>(height) * GetPitch();
@@ -405,8 +410,7 @@
     return true;
   }
   if (m_pAlphaMask) {
-    memset(m_pAlphaMask->GetBuffer(), 0xff,
-           m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch());
+    fxcrt::spanset(m_pAlphaMask->GetBuffer(), 0xff);
     return true;
   }
   const int destOffset = GetFormat() == FXDIB_Format::kArgb ? 3 : 0;
diff --git a/core/fxge/dib/cfx_dibitmap.h b/core/fxge/dib/cfx_dibitmap.h
index 0ac75c6..508cf89 100644
--- a/core/fxge/dib/cfx_dibitmap.h
+++ b/core/fxge/dib/cfx_dibitmap.h
@@ -33,7 +33,7 @@
   bool Copy(const RetainPtr<CFX_DIBBase>& pSrc);
 
   // CFX_DIBBase
-  uint8_t* GetBuffer() const override;
+  pdfium::span<uint8_t> GetBuffer() const override;
   pdfium::span<const uint8_t> GetScanline(int line) const override;
   size_t GetEstimatedImageMemoryBurden() const override;
 
diff --git a/core/fxge/dib/cfx_imagerenderer.cpp b/core/fxge/dib/cfx_imagerenderer.cpp
index e751902..2e7f496 100644
--- a/core/fxge/dib/cfx_imagerenderer.cpp
+++ b/core/fxge/dib/cfx_imagerenderer.cpp
@@ -95,7 +95,7 @@
     return true;
 
   RetainPtr<CFX_DIBitmap> pBitmap = m_pTransformer->DetachBitmap();
-  if (!pBitmap || !pBitmap->GetBuffer())
+  if (!pBitmap || pBitmap->GetBuffer().empty())
     return false;
 
   if (pBitmap->IsMaskFormat()) {
diff --git a/core/fxge/dib/cfx_imagetransformer.cpp b/core/fxge/dib/cfx_imagetransformer.cpp
index f65822d..835abe9 100644
--- a/core/fxge/dib/cfx_imagetransformer.cpp
+++ b/core/fxge/dib/cfx_imagetransformer.cpp
@@ -246,7 +246,8 @@
   if (!pTransformed->Create(m_result.Width(), m_result.Height(), format))
     return;
 
-  const uint8_t* pSrcMaskBuf = m_Storer.GetBitmap()->GetAlphaMaskBuffer();
+  pdfium::span<const uint8_t> pSrcMaskBuf =
+      m_Storer.GetBitmap()->GetAlphaMaskBuffer();
   pTransformed->Clear(0);
   RetainPtr<CFX_DIBitmap> pDestMask = pTransformed->GetAlphaMask();
   if (pDestMask)
@@ -256,20 +257,20 @@
                             m_result.top);
   result2stretch.Concat(m_dest2stretch);
   result2stretch.Translate(-m_StretchClip.left, -m_StretchClip.top);
-  if (!pSrcMaskBuf && pDestMask) {
+  if (pSrcMaskBuf.empty() && pDestMask) {
     pDestMask->Clear(0xff000000);
   } else if (pDestMask) {
     CalcData calc_data = {
         pDestMask.Get(),
         result2stretch,
-        pSrcMaskBuf,
+        pSrcMaskBuf.data(),
         m_Storer.GetBitmap()->GetAlphaMaskPitch(),
     };
     CalcMask(calc_data);
   }
 
   CalcData calc_data = {pTransformed.Get(), result2stretch,
-                        m_Storer.GetBitmap()->GetBuffer(),
+                        m_Storer.GetBitmap()->GetBuffer().data(),
                         m_Storer.GetBitmap()->GetPitch()};
   if (m_Storer.GetBitmap()->IsMaskFormat()) {
     CalcAlpha(calc_data);
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index 772de30..b51526a 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -102,7 +102,7 @@
   FXDIB_Format dest_format = pBitmap->GetFormat();
   FXDIB_Format src_format = pSrcBitmap->GetFormat();
   int pitch = pBitmap->GetPitch();
-  uint8_t* buffer = pBitmap->GetBuffer();
+  uint8_t* buffer = pBitmap->GetBuffer().data();
   if (dest_format == src_format) {
     for (int row = 0; row < height; row++) {
       uint8_t* dest_scan = buffer + (dest_top + row) * pitch + dest_left * Bpp;
@@ -300,7 +300,7 @@
     pdfium::span<const uint32_t> palette) {
   int width = source->GetWidth();
   int height = source->GetHeight();
-  void* buffer = source->GetBuffer();
+  void* buffer = source->GetBuffer().data();
   DCHECK(buffer);
   DataVector<uint32_t> dst32_storage(Fx2DSizeOrDie(width, height));
   pdfium::span<SkPMColor> dst32_pixels(dst32_storage);
@@ -714,7 +714,7 @@
               int* heightPtr,
               bool forceAlpha,
               bool bRgbByteOrder) {
-  void* buffer = pSource->GetBuffer();
+  void* buffer = pSource->GetBuffer().data();
   if (!buffer)
     return false;
   SkColorType colorType = forceAlpha || pSource->IsMaskFormat()
@@ -1735,7 +1735,8 @@
   SkImageInfo imageInfo =
       SkImageInfo::Make(pBitmap->GetWidth(), pBitmap->GetHeight(), color_type,
                         kOpaque_SkAlphaType);
-  skBitmap.installPixels(imageInfo, pBitmap->GetBuffer(), pBitmap->GetPitch());
+  skBitmap.installPixels(imageInfo, pBitmap->GetBuffer().data(),
+                         pBitmap->GetPitch());
   m_pCanvas = new SkCanvas(skBitmap);
 }
 
@@ -2033,7 +2034,7 @@
       SkImageInfo::Make(pThisLayer->GetWidth(), pThisLayer->GetHeight(),
                         SkColorType::kAlpha_8_SkColorType, kOpaque_SkAlphaType);
   SkBitmap bitmap;
-  bitmap.installPixels(imageInfo, pThisLayer->GetBuffer(),
+  bitmap.installPixels(imageInfo, pThisLayer->GetBuffer().data(),
                        pThisLayer->GetPitch());
   auto canvas = std::make_unique<SkCanvas>(bitmap);
   canvas->translate(
@@ -2419,7 +2420,7 @@
 }
 
 uint8_t* CFX_SkiaDeviceDriver::GetBuffer() const {
-  return m_pBitmap->GetBuffer();
+  return m_pBitmap->GetBuffer().data();
 }
 
 bool CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) {
@@ -2447,7 +2448,7 @@
                                      int top) {
   if (!m_pBitmap)
     return true;
-  uint8_t* srcBuffer = m_pBitmap->GetBuffer();
+  uint8_t* srcBuffer = m_pBitmap->GetBuffer().data();
   if (!srcBuffer)
     return true;
 #if defined(_SKIA_SUPPORT_)
@@ -2459,7 +2460,7 @@
       srcWidth, srcHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType);
   SkBitmap skSrcBitmap;
   skSrcBitmap.installPixels(srcImageInfo, srcBuffer, srcRowBytes);
-  uint8_t* dstBuffer = pBitmap->GetBuffer();
+  uint8_t* dstBuffer = pBitmap->GetBuffer().data();
   DCHECK(dstBuffer);
   int dstWidth = pBitmap->GetWidth();
   int dstHeight = pBitmap->GetHeight();
@@ -2519,7 +2520,7 @@
                                      int left,
                                      int top,
                                      BlendMode blend_type) {
-  if (!m_pBitmap || !m_pBitmap->GetBuffer())
+  if (!m_pBitmap || m_pBitmap->GetBuffer().empty())
     return true;
 
 #if defined(_SKIA_SUPPORT_)
@@ -2558,7 +2559,7 @@
                                          BlendMode blend_type) {
 #if defined(_SKIA_SUPPORT_)
   m_pCache->FlushForDraw();
-  if (!m_pBitmap->GetBuffer())
+  if (m_pBitmap->GetBuffer().empty())
     return true;
 
   CFX_Matrix m = CFX_RenderDevice::GetFlipMatrix(dest_width, dest_height,
@@ -2614,7 +2615,7 @@
 
 #if defined(_SKIA_SUPPORT_PATHS_)
   Flush();
-  if (!m_pBitmap->GetBuffer())
+  if (m_pBitmap->GetBuffer().empty())
     return true;
 
   *handle = std::make_unique<CFX_ImageRenderer>(
@@ -2633,7 +2634,7 @@
 
 #if defined(_SKIA_SUPPORT_PATHS_)
   Flush();
-  if (!m_pBitmap->GetBuffer()) {
+  if (m_pBitmap->GetBuffer().empty()) {
     return true;
   }
   return handle->Continue(pPause);
@@ -2651,7 +2652,7 @@
   if (this->GetBPP() != 32)
     return;
 
-  void* buffer = this->GetBuffer();
+  void* buffer = this->GetBuffer().data();
   if (!buffer)
     return;
 
@@ -2677,7 +2678,7 @@
   if (this->GetBPP() != 32)
     return;
 
-  void* buffer = this->GetBuffer();
+  void* buffer = this->GetBuffer().data();
   if (!buffer)
     return;
 
@@ -2757,7 +2758,7 @@
     int dest_top,
     int bitmap_alpha,
     BlendMode blend_type) {
-  if (!m_pBitmap || !m_pBitmap->GetBuffer())
+  if (!m_pBitmap || m_pBitmap->GetBuffer().empty())
     return true;
 
   CFX_Matrix m = CFX_RenderDevice::GetFlipMatrix(
@@ -2972,6 +2973,6 @@
 
 void CFX_DIBitmap::DebugVerifyBitmapIsPreMultiplied() const {
 #ifdef SK_DEBUG
-  DebugVerifyBufferIsPreMultiplied(GetBuffer());
+  DebugVerifyBufferIsPreMultiplied(GetBuffer().data());
 #endif  // SK_DEBUG
 }
diff --git a/core/fxge/win32/cgdi_device_driver.cpp b/core/fxge/win32/cgdi_device_driver.cpp
index db23f33..2045d1c 100644
--- a/core/fxge/win32/cgdi_device_driver.cpp
+++ b/core/fxge/win32/cgdi_device_driver.cpp
@@ -393,7 +393,7 @@
     if (!pBitmap)
       return false;
 
-    LPBYTE pBuffer = pBitmap->GetBuffer();
+    LPBYTE pBuffer = pBitmap->GetBuffer().data();
     ByteString info = GetBitmapInfo(pBitmap);
     ((BITMAPINFOHEADER*)info.c_str())->biHeight *= -1;
     FX_RECT dst_rect(0, 0, src_rect.Width(), src_rect.Height());
@@ -407,7 +407,7 @@
   }
 
   RetainPtr<CFX_DIBitmap> pBitmap = pBitmap1;
-  LPBYTE pBuffer = pBitmap->GetBuffer();
+  LPBYTE pBuffer = pBitmap->GetBuffer().data();
   ByteString info = GetBitmapInfo(pBitmap);
   ::SetDIBitsToDevice(m_hDC, left, top, src_rect.Width(), src_rect.Height(),
                       src_rect.left, pBitmap->GetHeight() - src_rect.bottom, 0,
@@ -445,7 +445,7 @@
   ByteString toStrechBitmapInfo = GetBitmapInfo(pToStrechBitmap);
   ::StretchDIBits(m_hDC, dest_left, dest_top, dest_width, dest_height, 0, 0,
                   pToStrechBitmap->GetWidth(), pToStrechBitmap->GetHeight(),
-                  pToStrechBitmap->GetBuffer(),
+                  pToStrechBitmap->GetBuffer().data(),
                   (BITMAPINFO*)toStrechBitmapInfo.c_str(), DIB_RGB_COLORS,
                   SRCCOPY);
   return true;
@@ -502,7 +502,7 @@
   // 0xB8074A
 
   ::StretchDIBits(m_hDC, dest_left, dest_top, dest_width, dest_height, 0, 0,
-                  width, height, pBitmap->GetBuffer(), (BITMAPINFO*)&bmi,
+                  width, height, pBitmap->GetBuffer().data(), (BITMAPINFO*)&bmi,
                   DIB_RGB_COLORS, 0xB8074A);
 
   SelectObject(m_hDC, hOld);
diff --git a/core/fxge/win32/cgdi_display_driver.cpp b/core/fxge/win32/cgdi_display_driver.cpp
index 947745b..7ba2d76 100644
--- a/core/fxge/win32/cgdi_display_driver.cpp
+++ b/core/fxge/win32/cgdi_display_driver.cpp
@@ -51,13 +51,13 @@
   bmi.bmiHeader.biPlanes = 1;
   bmi.bmiHeader.biWidth = width;
   if (pBitmap->GetBPP() > 8) {
-    ret = ::GetDIBits(hDCMemory, hbmp, 0, height, pBitmap->GetBuffer(), &bmi,
-                      DIB_RGB_COLORS) == height;
+    ret = ::GetDIBits(hDCMemory, hbmp, 0, height, pBitmap->GetBuffer().data(),
+                      &bmi, DIB_RGB_COLORS) == height;
   } else {
     auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
     if (bitmap->Create(width, height, FXDIB_Format::kRgb)) {
       bmi.bmiHeader.biBitCount = 24;
-      ::GetDIBits(hDCMemory, hbmp, 0, height, bitmap->GetBuffer(), &bmi,
+      ::GetDIBits(hDCMemory, hbmp, 0, height, bitmap->GetBuffer().data(), &bmi,
                   DIB_RGB_COLORS);
       ret = pBitmap->TransferBitmap(0, 0, width, height, bitmap, 0, 0);
     } else {
diff --git a/core/fxge/win32/cgdi_plus_ext.cpp b/core/fxge/win32/cgdi_plus_ext.cpp
index 945bbde..b665f56 100644
--- a/core/fxge/win32/cgdi_plus_ext.cpp
+++ b/core/fxge/win32/cgdi_plus_ext.cpp
@@ -221,8 +221,10 @@
     return;
   }
   int src_pitch = pBitmap->GetPitch();
-  uint8_t* scan0 = pBitmap->GetBuffer() + src_rect.top * src_pitch +
-                   pBitmap->GetBPP() * src_rect.left / 8;
+  uint8_t* scan0 = pBitmap->GetBuffer()
+                       .subspan(src_rect.top * src_pitch +
+                                pBitmap->GetBPP() * src_rect.left / 8)
+                       .data();
   Gdiplus::GpBitmap* bitmap = nullptr;
   switch (pBitmap->GetFormat()) {
     case FXDIB_Format::kArgb:
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index 8f93c66..7a93f8e 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -34,6 +34,7 @@
 #include "core/fxcrt/fx_safe_types.h"
 #include "core/fxcrt/fx_stream.h"
 #include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/span_util.h"
 #include "core/fxcrt/stl_util.h"
 #include "core/fxcrt/unowned_ptr.h"
 #include "core/fxge/cfx_defaultrenderdevice.h"
@@ -597,7 +598,8 @@
     if (win_dc.GetDeviceType() == DeviceType::kPrinter) {
       auto pDst = pdfium::MakeRetain<CFX_DIBitmap>();
       if (pDst->Create(size_x, size_y, FXDIB_Format::kRgb32)) {
-        memset(pDst->GetBuffer(), -1, pBitmap->GetPitch() * size_y);
+        fxcrt::spanset(pDst->GetBuffer().first(pBitmap->GetPitch() * size_y),
+                       -1);
         pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
                               BlendMode::kNormal, nullptr, false);
         win_dc.StretchDIBits(pDst, 0, 0, size_x, size_y);
@@ -911,7 +913,8 @@
 }
 
 FPDF_EXPORT void* FPDF_CALLCONV FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
-  return bitmap ? CFXDIBitmapFromFPDFBitmap(bitmap)->GetBuffer() : nullptr;
+  return bitmap ? CFXDIBitmapFromFPDFBitmap(bitmap)->GetBuffer().data()
+                : nullptr;
 }
 
 FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
diff --git a/fxbarcode/cfx_barcode_unittest.cpp b/fxbarcode/cfx_barcode_unittest.cpp
index 44e1175..41a3cd8 100644
--- a/fxbarcode/cfx_barcode_unittest.cpp
+++ b/fxbarcode/cfx_barcode_unittest.cpp
@@ -49,8 +49,7 @@
   bool RenderDevice() { return barcode_->RenderDevice(device_.get(), matrix_); }
 
   std::string BitmapChecksum() {
-    return GenerateMD5Base16(
-        {bitmap_->GetBuffer(), bitmap_->GetPitch() * bitmap_->GetHeight()});
+    return GenerateMD5Base16(bitmap_->GetBuffer());
   }
 
   // Manually insert calls to this as needed for debugging.
diff --git a/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc b/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc
index 59eda76..ec74f16 100644
--- a/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc
+++ b/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc
@@ -38,7 +38,7 @@
   Jbig2Context jbig2_context;
   FXCODEC_STATUS status = Jbig2Decoder::StartDecode(
       &jbig2_context, &document_context, width, height, {data, size}, 1, {}, 0,
-      bitmap->GetBuffer(), bitmap->GetPitch(), nullptr);
+      bitmap->GetBuffer().data(), bitmap->GetPitch(), nullptr);
 
   while (status == FXCODEC_STATUS::kDecodeToBeContinued)
     status = Jbig2Decoder::ContinueDecode(&jbig2_context, nullptr);
diff --git a/testing/fuzzers/pdf_jpx_fuzzer.cc b/testing/fuzzers/pdf_jpx_fuzzer.cc
index ef88c7f..bf191ab 100644
--- a/testing/fuzzers/pdf_jpx_fuzzer.cc
+++ b/testing/fuzzers/pdf_jpx_fuzzer.cc
@@ -69,7 +69,7 @@
           static_cast<uint32_t>(bitmap->GetHeight()))
     return 0;
 
-  decoder->Decode(bitmap->GetBuffer(), bitmap->GetPitch(),
+  decoder->Decode(bitmap->GetBuffer().data(), bitmap->GetPitch(),
                   /*swap_rgb=*/false);
 
   return 0;
diff --git a/testing/fuzzers/pdf_scanlinecompositor_fuzzer.cc b/testing/fuzzers/pdf_scanlinecompositor_fuzzer.cc
index c16f949..9c6e434 100644
--- a/testing/fuzzers/pdf_scanlinecompositor_fuzzer.cc
+++ b/testing/fuzzers/pdf_scanlinecompositor_fuzzer.cc
@@ -70,7 +70,7 @@
       !dest_bitmap->Create(width, height, dest_format)) {
     return 0;
   }
-  if (!src_bitmap->GetBuffer() || !dest_bitmap->GetBuffer()) {
+  if (src_bitmap->GetBuffer().empty() || dest_bitmap->GetBuffer().empty()) {
     return 0;
   }
 
diff --git a/xfa/fgas/graphics/cfgas_gegraphics.cpp b/xfa/fgas/graphics/cfgas_gegraphics.cpp
index cc8f3dc..c909183 100644
--- a/xfa/fgas/graphics/cfgas_gegraphics.cpp
+++ b/xfa/fgas/graphics/cfgas_gegraphics.cpp
@@ -13,6 +13,7 @@
 #include <utility>
 
 #include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/span_util.h"
 #include "core/fxge/cfx_defaultrenderdevice.h"
 #include "core/fxge/cfx_renderdevice.h"
 #include "core/fxge/cfx_unicodeencoding.h"
@@ -259,7 +260,9 @@
 
   auto mask = pdfium::MakeRetain<CFX_DIBitmap>();
   mask->Create(data.width, data.height, FXDIB_Format::k1bppMask);
-  memcpy(mask->GetBuffer(), data.maskBits, mask->GetPitch() * data.height);
+  fxcrt::spancpy(
+      mask->GetBuffer(),
+      pdfium::make_span(data.maskBits).first(mask->GetPitch() * data.height));
   const CFX_FloatRect rectf =
       matrix.TransformRect(path.GetPath().GetBoundingBox());
   const FX_RECT rect = rectf.ToRoundedFxRect();
diff --git a/xfa/fxfa/cxfa_ffwidget.cpp b/xfa/fxfa/cxfa_ffwidget.cpp
index aa30e19..727d2a0 100644
--- a/xfa/fxfa/cxfa_ffwidget.cpp
+++ b/xfa/fxfa/cxfa_ffwidget.cpp
@@ -77,7 +77,8 @@
                    XFA_AttributeValue iVertAlign) {
   if (rtImage.IsEmpty())
     return;
-  if (!pDIBitmap || !pDIBitmap->GetBuffer())
+
+  if (!pDIBitmap || pDIBitmap->GetBuffer().empty())
     return;
 
   CFX_RectF rtFit(rtImage.TopLeft(),