Mass suppress unsafe buffers in fxge drivers.

Bug: 42271175
Change-Id: I419a299ef88c870563621bff96c031a3eb8819a9
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/120210
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxge/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp
index 76d8ea1..908a129 100644
--- a/core/fxge/agg/fx_agg_driver.cpp
+++ b/core/fxge/agg/fx_agg_driver.cpp
@@ -4,11 +4,6 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
-#if defined(UNSAFE_BUFFERS_BUILD)
-// TODO(crbug.com/pdfium/2154): resolve buffer safety issues.
-#pragma allow_unsafe_buffers
-#endif
-
 #include "core/fxge/agg/fx_agg_driver.h"
 
 #include <math.h>
@@ -20,6 +15,7 @@
 #include "build/build_config.h"
 #include "core/fxcrt/check.h"
 #include "core/fxcrt/check_op.h"
+#include "core/fxcrt/compiler_specific.h"
 #include "core/fxcrt/fx_2d_size.h"
 #include "core/fxcrt/fx_safe_types.h"
 #include "core/fxcrt/notreached.h"
@@ -80,58 +76,61 @@
   int Bpp = pBitmap->GetBPP() / 8;
   int dib_argb = FXARGB_TOBGRORDERDIB(argb);
   pdfium::span<uint8_t> pBuffer = pBitmap->GetWritableBuffer();
-  if (src_alpha == 255) {
+  UNSAFE_TODO({
+    if (src_alpha == 255) {
+      for (int row = rect.top; row < rect.bottom; row++) {
+        uint8_t* dest_scan =
+            pBuffer.subspan(row * pBitmap->GetPitch() + rect.left * Bpp).data();
+        if (Bpp == 4) {
+          std::fill_n(reinterpret_cast<uint32_t*>(dest_scan), width, dib_argb);
+        } else {
+          for (int col = 0; col < width; col++) {
+            *dest_scan++ = src_r;
+            *dest_scan++ = src_g;
+            *dest_scan++ = src_b;
+          }
+        }
+      }
+      return;
+    }
+    bool bAlpha = pBitmap->IsAlphaFormat();
     for (int row = rect.top; row < rect.bottom; row++) {
       uint8_t* dest_scan =
           pBuffer.subspan(row * pBitmap->GetPitch() + rect.left * Bpp).data();
-      if (Bpp == 4) {
-        std::fill_n(reinterpret_cast<uint32_t*>(dest_scan), width, dib_argb);
-      } else {
+      if (bAlpha) {
         for (int col = 0; col < width; col++) {
-          *dest_scan++ = src_r;
-          *dest_scan++ = src_g;
-          *dest_scan++ = src_b;
+          uint8_t back_alpha = dest_scan[3];
+          if (back_alpha == 0) {
+            FXARGB_SetRGBOrderDIB(dest_scan, argb);
+            dest_scan += 4;
+            continue;
+          }
+          uint8_t dest_alpha =
+              back_alpha + src_alpha - back_alpha * src_alpha / 255;
+          dest_scan[3] = dest_alpha;
+          int alpha_ratio = src_alpha * 255 / dest_alpha;
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
+          dest_scan++;
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
+          dest_scan++;
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
+          dest_scan += 2;
         }
+        continue;
       }
-    }
-    return;
-  }
-  bool bAlpha = pBitmap->IsAlphaFormat();
-  for (int row = rect.top; row < rect.bottom; row++) {
-    uint8_t* dest_scan =
-        pBuffer.subspan(row * pBitmap->GetPitch() + rect.left * Bpp).data();
-    if (bAlpha) {
       for (int col = 0; col < width; col++) {
-        uint8_t back_alpha = dest_scan[3];
-        if (back_alpha == 0) {
-          FXARGB_SetRGBOrderDIB(dest_scan, argb);
-          dest_scan += 4;
-          continue;
+        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
+        dest_scan++;
+        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
+        dest_scan++;
+        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
+        dest_scan++;
+        if (Bpp == 4) {
+          dest_scan++;
         }
-        uint8_t dest_alpha =
-            back_alpha + src_alpha - back_alpha * src_alpha / 255;
-        dest_scan[3] = dest_alpha;
-        int alpha_ratio = src_alpha * 255 / dest_alpha;
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
-        dest_scan++;
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
-        dest_scan++;
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
-        dest_scan += 2;
       }
-      continue;
     }
-    for (int col = 0; col < width; col++) {
-      *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
-      dest_scan++;
-      *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
-      dest_scan++;
-      *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
-      dest_scan++;
-      if (Bpp == 4)
-        dest_scan++;
-    }
-  }
+  });
 }
 
 void RgbByteOrderTransferBitmap(RetainPtr<CFX_DIBitmap> pBitmap,
@@ -159,59 +158,79 @@
   pdfium::span<uint8_t> dest_span = pBitmap->GetWritableBuffer()
                                         .subspan(dest_y_offset)
                                         .subspan(dest_x_offset);
-  if (dest_format == src_format) {
-    const size_t src_x_offset = Fx2DSizeOrDie(src_left, Bpp);
-    for (int row = 0; row < height; row++) {
-      uint8_t* dest_scan = dest_span.data();
-      const uint8_t* src_scan =
-          pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data();
-      if (Bpp == 4) {
-        for (int col = 0; col < width; col++) {
-          FXARGB_SetRGBOrderDIB(dest_scan,
-                                *reinterpret_cast<const uint32_t*>(src_scan));
-          dest_scan += 4;
-          src_scan += 4;
+  UNSAFE_TODO({
+    if (dest_format == src_format) {
+      const size_t src_x_offset = Fx2DSizeOrDie(src_left, Bpp);
+      for (int row = 0; row < height; row++) {
+        uint8_t* dest_scan = dest_span.data();
+        const uint8_t* src_scan =
+            pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data();
+        if (Bpp == 4) {
+          for (int col = 0; col < width; col++) {
+            FXARGB_SetRGBOrderDIB(dest_scan,
+                                  *reinterpret_cast<const uint32_t*>(src_scan));
+            dest_scan += 4;
+            src_scan += 4;
+          }
+        } else {
+          for (int col = 0; col < width; col++) {
+            *dest_scan++ = src_scan[2];
+            *dest_scan++ = src_scan[1];
+            *dest_scan++ = src_scan[0];
+            src_scan += 3;
+          }
         }
-      } else {
+        dest_span = dest_span.subspan(dest_pitch);
+      }
+      return;
+    }
+
+    if (dest_format == FXDIB_Format::kRgb) {
+      DCHECK_EQ(src_format, FXDIB_Format::kRgb32);
+      const size_t src_x_offset = Fx2DSizeOrDie(src_left, 4);
+      for (int row = 0; row < height; row++) {
+        uint8_t* dest_scan = dest_span.data();
+        const uint8_t* src_scan =
+            pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data();
         for (int col = 0; col < width; col++) {
           *dest_scan++ = src_scan[2];
           *dest_scan++ = src_scan[1];
           *dest_scan++ = src_scan[0];
-          src_scan += 3;
+          src_scan += 4;
+        }
+        if (row < height - 1) {
+          // Since `dest_scan` was initialized in a way that takes
+          // `dest_x_offset` and `dest_y_offset` into account, it may go past
+          // the end of the span after processing the last row.
+          dest_span = dest_span.subspan(dest_pitch);
         }
       }
-      dest_span = dest_span.subspan(dest_pitch);
+      return;
     }
-    return;
-  }
 
-  if (dest_format == FXDIB_Format::kRgb) {
-    DCHECK_EQ(src_format, FXDIB_Format::kRgb32);
-    const size_t src_x_offset = Fx2DSizeOrDie(src_left, 4);
-    for (int row = 0; row < height; row++) {
-      uint8_t* dest_scan = dest_span.data();
-      const uint8_t* src_scan =
-          pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data();
-      for (int col = 0; col < width; col++) {
-        *dest_scan++ = src_scan[2];
-        *dest_scan++ = src_scan[1];
-        *dest_scan++ = src_scan[0];
-        src_scan += 4;
-      }
-      if (row < height - 1) {
-        // Since `dest_scan` was initialized in a way that takes `dest_x_offset`
-        // and `dest_y_offset` into account, it may go past the end of the span
-        // after processing the last row.
+    DCHECK(dest_format == FXDIB_Format::kArgb ||
+           dest_format == FXDIB_Format::kRgb32);
+    if (src_format == FXDIB_Format::kRgb) {
+      const size_t src_x_offset = Fx2DSizeOrDie(src_left, 3);
+      for (int row = 0; row < height; row++) {
+        uint8_t* dest_scan = dest_span.data();
+        const uint8_t* src_scan =
+            pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data();
+        for (int col = 0; col < width; col++) {
+          FXARGB_SetDIB(dest_scan, ArgbEncode(0xff, src_scan[0], src_scan[1],
+                                              src_scan[2]));
+          dest_scan += 4;
+          src_scan += 3;
+        }
         dest_span = dest_span.subspan(dest_pitch);
       }
+      return;
     }
-    return;
-  }
-
-  DCHECK(dest_format == FXDIB_Format::kArgb ||
-         dest_format == FXDIB_Format::kRgb32);
-  if (src_format == FXDIB_Format::kRgb) {
-    const size_t src_x_offset = Fx2DSizeOrDie(src_left, 3);
+    if (src_format != FXDIB_Format::kRgb32) {
+      return;
+    }
+    DCHECK_EQ(dest_format, FXDIB_Format::kArgb);
+    const size_t src_x_offset = Fx2DSizeOrDie(src_left, 4);
     for (int row = 0; row < height; row++) {
       uint8_t* dest_scan = dest_span.data();
       const uint8_t* src_scan =
@@ -219,29 +238,12 @@
       for (int col = 0; col < width; col++) {
         FXARGB_SetDIB(dest_scan,
                       ArgbEncode(0xff, src_scan[0], src_scan[1], src_scan[2]));
+        src_scan += 4;
         dest_scan += 4;
-        src_scan += 3;
       }
       dest_span = dest_span.subspan(dest_pitch);
     }
-    return;
-  }
-  if (src_format != FXDIB_Format::kRgb32)
-    return;
-  DCHECK_EQ(dest_format, FXDIB_Format::kArgb);
-  const size_t src_x_offset = Fx2DSizeOrDie(src_left, 4);
-  for (int row = 0; row < height; row++) {
-    uint8_t* dest_scan = dest_span.data();
-    const uint8_t* src_scan =
-        pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data();
-    for (int col = 0; col < width; col++) {
-      FXARGB_SetDIB(dest_scan,
-                    ArgbEncode(0xff, src_scan[0], src_scan[1], src_scan[2]));
-      src_scan += 4;
-      dest_scan += 4;
-    }
-    dest_span = dest_span.subspan(dest_pitch);
-  }
+  });
 }
 
 void RasterizeStroke(agg::rasterizer_scanline_aa* rasterizer,
@@ -421,14 +423,15 @@
   }
 
   inline int GetSrcAlpha(const uint8_t* clip_scan, int col) const {
-    return clip_scan ? m_Alpha * clip_scan[col] / 255 : m_Alpha;
+    return clip_scan ? m_Alpha * UNSAFE_TODO(clip_scan[col]) / 255 : m_Alpha;
   }
 
   inline int GetSourceAlpha(const uint8_t* cover_scan,
                             const uint8_t* clip_scan,
                             int col) const {
-    return clip_scan ? m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255
-                     : m_Alpha * cover_scan[col] / 255;
+    return UNSAFE_TODO(clip_scan ? m_Alpha * cover_scan[col] * clip_scan[col] /
+                                       255 / 255
+                                 : m_Alpha * cover_scan[col] / 255);
   }
 
   inline int GetColStart(int span_left, int clip_left) const {
@@ -468,136 +471,139 @@
                                  const uint8_t* clip_scan) {
   int col_start = GetColStart(span_left, clip_left);
   int col_end = GetColEnd(span_left, span_len, clip_right);
-  if (Bpp) {
-    dest_scan += col_start * Bpp;
-    backdrop_scan += col_start * Bpp;
-  } else {
-    dest_scan += col_start / 8;
-    backdrop_scan += col_start / 8;
-  }
-  if (m_bRgbByteOrder) {
-    if (Bpp == 4 && bDestAlpha) {
-      for (int col = col_start; col < col_end; col++) {
-        int src_alpha = GetSrcAlpha(clip_scan, col);
-        uint8_t dest_alpha =
-            backdrop_scan[3] + src_alpha - backdrop_scan[3] * src_alpha / 255;
-        dest_scan[3] = dest_alpha;
-        int alpha_ratio = src_alpha * 255 / dest_alpha;
-        if (m_bFullCover) {
-          *dest_scan++ =
-              FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, alpha_ratio);
-          *dest_scan++ =
-              FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, alpha_ratio);
-          *dest_scan++ =
-              FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, alpha_ratio);
-          dest_scan++;
-          backdrop_scan++;
-        } else {
-          int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, alpha_ratio);
-          int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, alpha_ratio);
-          int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, alpha_ratio);
-          backdrop_scan++;
+  UNSAFE_TODO({
+    if (Bpp) {
+      dest_scan += col_start * Bpp;
+      backdrop_scan += col_start * Bpp;
+    } else {
+      dest_scan += col_start / 8;
+      backdrop_scan += col_start / 8;
+    }
+    if (m_bRgbByteOrder) {
+      if (Bpp == 4 && bDestAlpha) {
+        for (int col = col_start; col < col_end; col++) {
+          int src_alpha = GetSrcAlpha(clip_scan, col);
+          uint8_t dest_alpha =
+              backdrop_scan[3] + src_alpha - backdrop_scan[3] * src_alpha / 255;
+          dest_scan[3] = dest_alpha;
+          int alpha_ratio = src_alpha * 255 / dest_alpha;
+          if (m_bFullCover) {
+            *dest_scan++ =
+                FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, alpha_ratio);
+            *dest_scan++ =
+                FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, alpha_ratio);
+            *dest_scan++ =
+                FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, alpha_ratio);
+            dest_scan++;
+            backdrop_scan++;
+          } else {
+            int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, alpha_ratio);
+            int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, alpha_ratio);
+            int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, alpha_ratio);
+            backdrop_scan++;
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
+            dest_scan++;
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
+            dest_scan++;
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
+            dest_scan += 2;
+          }
+        }
+        return;
+      }
+      if (Bpp == 3 || Bpp == 4) {
+        for (int col = col_start; col < col_end; col++) {
+          int src_alpha = GetSrcAlpha(clip_scan, col);
+          int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, src_alpha);
+          int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha);
+          int b = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Blue, src_alpha);
+          backdrop_scan += Bpp - 2;
           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
           dest_scan++;
           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
           dest_scan++;
           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
-          dest_scan += 2;
+          dest_scan += Bpp - 2;
         }
       }
       return;
     }
+    if (Bpp == 4 && bDestAlpha) {
+      for (int col = col_start; col < col_end; col++) {
+        int src_alpha = GetSrcAlpha(clip_scan, col);
+        int src_alpha_covered = src_alpha * cover_scan[col] / 255;
+        if (src_alpha_covered == 0) {
+          dest_scan += 4;
+          continue;
+        }
+        if (cover_scan[col] == 255) {
+          dest_scan[3] = src_alpha_covered;
+          *dest_scan++ = m_Blue;
+          *dest_scan++ = m_Green;
+          *dest_scan = m_Red;
+          dest_scan += 2;
+          continue;
+        }
+        if (dest_scan[3] == 0) {
+          dest_scan[3] = src_alpha_covered;
+          *dest_scan++ = m_Blue;
+          *dest_scan++ = m_Green;
+          *dest_scan = m_Red;
+          dest_scan += 2;
+          continue;
+        }
+        uint8_t cover = cover_scan[col];
+        dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover);
+        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover);
+        dest_scan++;
+        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover);
+        dest_scan++;
+        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover);
+        dest_scan += 2;
+      }
+      return;
+    }
     if (Bpp == 3 || Bpp == 4) {
       for (int col = col_start; col < col_end; col++) {
         int src_alpha = GetSrcAlpha(clip_scan, col);
-        int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, src_alpha);
+        if (m_bFullCover) {
+          *dest_scan++ = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, src_alpha);
+          *dest_scan++ =
+              FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha);
+          *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Red, src_alpha);
+          dest_scan += Bpp - 2;
+          backdrop_scan += Bpp - 2;
+          continue;
+        }
+        int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, src_alpha);
         int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha);
-        int b = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Blue, src_alpha);
+        int r = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Red, src_alpha);
         backdrop_scan += Bpp - 2;
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
+        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
         dest_scan++;
         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
         dest_scan++;
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
+        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
         dest_scan += Bpp - 2;
       }
+      return;
     }
-    return;
-  }
-  if (Bpp == 4 && bDestAlpha) {
-    for (int col = col_start; col < col_end; col++) {
-      int src_alpha = GetSrcAlpha(clip_scan, col);
-      int src_alpha_covered = src_alpha * cover_scan[col] / 255;
-      if (src_alpha_covered == 0) {
-        dest_scan += 4;
-        continue;
+    if (Bpp == 1) {
+      for (int col = col_start; col < col_end; col++) {
+        int src_alpha = GetSrcAlpha(clip_scan, col);
+        if (m_bFullCover) {
+          *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Gray, src_alpha);
+          continue;
+        }
+        int gray = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Gray, src_alpha);
+        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]);
+        dest_scan++;
       }
-      if (cover_scan[col] == 255) {
-        dest_scan[3] = src_alpha_covered;
-        *dest_scan++ = m_Blue;
-        *dest_scan++ = m_Green;
-        *dest_scan = m_Red;
-        dest_scan += 2;
-        continue;
-      }
-      if (dest_scan[3] == 0) {
-        dest_scan[3] = src_alpha_covered;
-        *dest_scan++ = m_Blue;
-        *dest_scan++ = m_Green;
-        *dest_scan = m_Red;
-        dest_scan += 2;
-        continue;
-      }
-      uint8_t cover = cover_scan[col];
-      dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover);
-      *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover);
-      dest_scan++;
-      *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover);
-      dest_scan++;
-      *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover);
-      dest_scan += 2;
+      return;
     }
-    return;
-  }
-  if (Bpp == 3 || Bpp == 4) {
-    for (int col = col_start; col < col_end; col++) {
-      int src_alpha = GetSrcAlpha(clip_scan, col);
-      if (m_bFullCover) {
-        *dest_scan++ = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, src_alpha);
-        *dest_scan++ = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha);
-        *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Red, src_alpha);
-        dest_scan += Bpp - 2;
-        backdrop_scan += Bpp - 2;
-        continue;
-      }
-      int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, src_alpha);
-      int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha);
-      int r = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Red, src_alpha);
-      backdrop_scan += Bpp - 2;
-      *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
-      dest_scan++;
-      *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
-      dest_scan++;
-      *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
-      dest_scan += Bpp - 2;
-    }
-    return;
-  }
-  if (Bpp == 1) {
-    for (int col = col_start; col < col_end; col++) {
-      int src_alpha = GetSrcAlpha(clip_scan, col);
-      if (m_bFullCover) {
-        *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Gray, src_alpha);
-        continue;
-      }
-      int gray = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Gray, src_alpha);
-      *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]);
-      dest_scan++;
-    }
-    return;
-  }
-  CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan, clip_scan,
-                          span_left);
+    CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan,
+                            clip_scan, span_left);
+  });
 }
 
 void CFX_Renderer::CompositeSpan1bpp(uint8_t* dest_scan,
@@ -611,7 +617,7 @@
   DCHECK(!m_bRgbByteOrder);
   int col_start = GetColStart(span_left, clip_left);
   int col_end = GetColEnd(span_left, span_len, clip_right);
-  dest_scan += col_start / 8;
+  UNSAFE_TODO(dest_scan += col_start / 8);
   CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan, clip_scan,
                           span_left);
 }
@@ -627,17 +633,20 @@
   DCHECK(!m_bRgbByteOrder);
   int col_start = GetColStart(span_left, clip_left);
   int col_end = GetColEnd(span_left, span_len, clip_right);
-  dest_scan += col_start;
-  for (int col = col_start; col < col_end; col++) {
-    int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
-    if (src_alpha) {
-      if (src_alpha == 255)
-        *dest_scan = m_Gray;
-      else
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
+  UNSAFE_TODO({
+    dest_scan += col_start;
+    for (int col = col_start; col < col_end; col++) {
+      int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
+      if (src_alpha) {
+        if (src_alpha == 255) {
+          *dest_scan = m_Gray;
+        } else {
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
+        }
+      }
+      dest_scan++;
     }
-    dest_scan++;
-  }
+  });
 }
 
 void CFX_Renderer::CompositeSpanARGB(uint8_t* dest_scan,
@@ -650,8 +659,34 @@
                                      const uint8_t* clip_scan) {
   int col_start = GetColStart(span_left, clip_left);
   int col_end = GetColEnd(span_left, span_len, clip_right);
-  dest_scan += col_start * Bpp;
-  if (m_bRgbByteOrder) {
+  UNSAFE_TODO({
+    dest_scan += col_start * Bpp;
+    if (m_bRgbByteOrder) {
+      for (int col = col_start; col < col_end; col++) {
+        int src_alpha = m_bFullCover
+                            ? GetSrcAlpha(clip_scan, col)
+                            : GetSourceAlpha(cover_scan, clip_scan, col);
+        if (src_alpha) {
+          if (src_alpha == 255) {
+            *(reinterpret_cast<uint32_t*>(dest_scan)) = m_Color;
+          } else {
+            uint8_t dest_alpha =
+                dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
+            dest_scan[3] = dest_alpha;
+            int alpha_ratio = src_alpha * 255 / dest_alpha;
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
+            dest_scan++;
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
+            dest_scan++;
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
+            dest_scan += 2;
+            continue;
+          }
+        }
+        dest_scan += 4;
+      }
+      return;
+    }
     for (int col = col_start; col < col_end; col++) {
       int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col)
                                    : GetSourceAlpha(cover_scan, clip_scan, col);
@@ -659,53 +694,30 @@
         if (src_alpha == 255) {
           *(reinterpret_cast<uint32_t*>(dest_scan)) = m_Color;
         } else {
+          if (dest_scan[3] == 0) {
+            dest_scan[3] = src_alpha;
+            *dest_scan++ = m_Blue;
+            *dest_scan++ = m_Green;
+            *dest_scan = m_Red;
+            dest_scan += 2;
+            continue;
+          }
           uint8_t dest_alpha =
               dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
           dest_scan[3] = dest_alpha;
           int alpha_ratio = src_alpha * 255 / dest_alpha;
-          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
           dest_scan++;
           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
           dest_scan++;
-          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
           dest_scan += 2;
           continue;
         }
       }
-      dest_scan += 4;
+      dest_scan += Bpp;
     }
-    return;
-  }
-  for (int col = col_start; col < col_end; col++) {
-    int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col)
-                                 : GetSourceAlpha(cover_scan, clip_scan, col);
-    if (src_alpha) {
-      if (src_alpha == 255) {
-        *(reinterpret_cast<uint32_t*>(dest_scan)) = m_Color;
-      } else {
-        if (dest_scan[3] == 0) {
-          dest_scan[3] = src_alpha;
-          *dest_scan++ = m_Blue;
-          *dest_scan++ = m_Green;
-          *dest_scan = m_Red;
-          dest_scan += 2;
-          continue;
-        }
-        uint8_t dest_alpha =
-            dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
-        dest_scan[3] = dest_alpha;
-        int alpha_ratio = src_alpha * 255 / dest_alpha;
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
-        dest_scan++;
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
-        dest_scan++;
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
-        dest_scan += 2;
-        continue;
-      }
-    }
-    dest_scan += Bpp;
-  }
+  });
 }
 
 void CFX_Renderer::CompositeSpanRGB(uint8_t* dest_scan,
@@ -718,59 +730,61 @@
                                     const uint8_t* clip_scan) {
   int col_start = GetColStart(span_left, clip_left);
   int col_end = GetColEnd(span_left, span_len, clip_right);
-  dest_scan += col_start * Bpp;
-  if (m_bRgbByteOrder) {
+  UNSAFE_TODO({
+    dest_scan += col_start * Bpp;
+    if (m_bRgbByteOrder) {
+      for (int col = col_start; col < col_end; col++) {
+        int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
+        if (src_alpha) {
+          if (src_alpha == 255) {
+            if (Bpp == 4) {
+              *(uint32_t*)dest_scan = m_Color;
+            } else if (Bpp == 3) {
+              *dest_scan++ = m_Red;
+              *dest_scan++ = m_Green;
+              *dest_scan++ = m_Blue;
+              continue;
+            }
+          } else {
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
+            dest_scan++;
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
+            dest_scan++;
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
+            dest_scan += Bpp - 2;
+            continue;
+          }
+        }
+        dest_scan += Bpp;
+      }
+      return;
+    }
     for (int col = col_start; col < col_end; col++) {
-      int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
+      int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col)
+                                   : GetSourceAlpha(cover_scan, clip_scan, col);
       if (src_alpha) {
         if (src_alpha == 255) {
           if (Bpp == 4) {
             *(uint32_t*)dest_scan = m_Color;
           } else if (Bpp == 3) {
-            *dest_scan++ = m_Red;
-            *dest_scan++ = m_Green;
             *dest_scan++ = m_Blue;
+            *dest_scan++ = m_Green;
+            *dest_scan++ = m_Red;
             continue;
           }
         } else {
-          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
           dest_scan++;
           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
           dest_scan++;
-          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
           dest_scan += Bpp - 2;
           continue;
         }
       }
       dest_scan += Bpp;
     }
-    return;
-  }
-  for (int col = col_start; col < col_end; col++) {
-    int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col)
-                                 : GetSourceAlpha(cover_scan, clip_scan, col);
-    if (src_alpha) {
-      if (src_alpha == 255) {
-        if (Bpp == 4) {
-          *(uint32_t*)dest_scan = m_Color;
-        } else if (Bpp == 3) {
-          *dest_scan++ = m_Blue;
-          *dest_scan++ = m_Green;
-          *dest_scan++ = m_Red;
-          continue;
-        }
-      } else {
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
-        dest_scan++;
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
-        dest_scan++;
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
-        dest_scan += Bpp - 2;
-        continue;
-      }
-    }
-    dest_scan += Bpp;
-  }
+  });
 }
 
 CFX_Renderer::CFX_Renderer(const RetainPtr<CFX_DIBitmap>& pDevice,
@@ -819,39 +833,43 @@
   bool bDestAlpha = m_pDevice->IsAlphaFormat() || m_pDevice->IsMaskFormat();
   unsigned num_spans = sl.num_spans();
   typename Scanline::const_iterator span = sl.begin();
-  while (true) {
-    if (span->len <= 0)
-      break;
+  UNSAFE_TODO({
+    while (true) {
+      if (span->len <= 0) {
+        break;
+      }
 
-    int x = span->x;
-    uint8_t* dest_pos = nullptr;
-    const uint8_t* backdrop_pos = nullptr;
-    if (Bpp) {
-      backdrop_pos = backdrop_scan ? backdrop_scan + x * Bpp : nullptr;
-      dest_pos = dest_scan + x * Bpp;
-    } else {
-      dest_pos = dest_scan + x / 8;
-      backdrop_pos = backdrop_scan ? backdrop_scan + x / 8 : nullptr;
-    }
-    const uint8_t* clip_pos = nullptr;
-    if (m_pClipMask) {
-      // TODO(crbug.com/1382604): use subspan arithmetic.
-      clip_pos = m_pClipMask->GetBuffer().data() +
-                 (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x -
-                 m_ClipBox.left;
-    }
-    if (backdrop_pos) {
-      CompositeSpan(dest_pos, backdrop_pos, Bpp, bDestAlpha, x, span->len,
-                    span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos);
-    } else {
-      (this->*m_CompositeSpanFunc)(dest_pos, Bpp, x, span->len, span->covers,
-                                   m_ClipBox.left, m_ClipBox.right, clip_pos);
-    }
-    if (--num_spans == 0)
-      break;
+      int x = span->x;
+      uint8_t* dest_pos = nullptr;
+      const uint8_t* backdrop_pos = nullptr;
+      if (Bpp) {
+        backdrop_pos = backdrop_scan ? backdrop_scan + x * Bpp : nullptr;
+        dest_pos = dest_scan + x * Bpp;
+      } else {
+        dest_pos = dest_scan + x / 8;
+        backdrop_pos = backdrop_scan ? backdrop_scan + x / 8 : nullptr;
+      }
+      const uint8_t* clip_pos = nullptr;
+      if (m_pClipMask) {
+        // TODO(crbug.com/1382604): use subspan arithmetic.
+        clip_pos = m_pClipMask->GetBuffer().data() +
+                   (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x -
+                   m_ClipBox.left;
+      }
+      if (backdrop_pos) {
+        CompositeSpan(dest_pos, backdrop_pos, Bpp, bDestAlpha, x, span->len,
+                      span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos);
+      } else {
+        (this->*m_CompositeSpanFunc)(dest_pos, Bpp, x, span->len, span->covers,
+                                     m_ClipBox.left, m_ClipBox.right, clip_pos);
+      }
+      if (--num_spans == 0) {
+        break;
+      }
 
-    ++span;
-  }
+      ++span;
+    }
+  });
 }
 
 void CFX_Renderer::CompositeSpan1bppHelper(uint8_t* dest_scan,
@@ -870,16 +888,19 @@
     index = (static_cast<uint8_t>(m_Color) == 0xff) ? 1 : 0;
   }
   uint8_t* dest_scan1 = dest_scan;
-  for (int col = col_start; col < col_end; col++) {
-    int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
-    if (src_alpha) {
-      if (!index)
-        *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8));
-      else
-        *dest_scan1 |= 1 << (7 - (col + span_left) % 8);
+  UNSAFE_TODO({
+    for (int col = col_start; col < col_end; col++) {
+      int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
+      if (src_alpha) {
+        if (!index) {
+          *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8));
+        } else {
+          *dest_scan1 |= 1 << (7 - (col + span_left) % 8);
+        }
+      }
+      dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8;
     }
-    dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8;
-  }
+  });
 }
 
 template <class BaseRenderer>
@@ -909,7 +930,7 @@
       if (--num_spans == 0)
         break;
 
-      ++span;
+      UNSAFE_TODO(++span);
     }
   }
 
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index ff349e4..7620c7e 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -2,11 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#if defined(UNSAFE_BUFFERS_BUILD)
-// TODO(crbug.com/pdfium/2154): resolve buffer safety issues.
-#pragma allow_unsafe_buffers
-#endif
-
 #include "core/fxge/skia/fx_skia_device.h"
 
 #include <math.h>
@@ -349,25 +344,28 @@
 
   float colors_min[3];
   float colors_max[3];
-  for (int i = 0; i < 3; ++i) {
-    colors_min[i] = func->GetRange(i * 2);
-    colors_max[i] = func->GetRange(i * 2 + 1);
-  }
-  pdfium::span<const uint8_t> sample_data = func->GetSampleStream()->GetSpan();
-  CFX_BitStream bitstream(sample_data);
-  for (uint32_t i = 0; i < sample_count; ++i) {
-    float float_colors[3];
-    for (uint32_t j = 0; j < 3; ++j) {
-      float sample = static_cast<float>(bitstream.GetBits(sample_size));
-      float interp = sample / (sample_count - 1);
-      float_colors[j] =
-          colors_min[j] + (colors_max[j] - colors_min[j]) * interp;
+  UNSAFE_TODO({
+    for (int i = 0; i < 3; ++i) {
+      colors_min[i] = func->GetRange(i * 2);
+      colors_max[i] = func->GetRange(i * 2 + 1);
     }
-    colors.push_back(SkPackARGB32NoCheck(0xFF, FloatToByte(float_colors[0]),
-                                         FloatToByte(float_colors[1]),
-                                         FloatToByte(float_colors[2])));
-    pos.push_back(static_cast<float>(i) / (sample_count - 1));
-  }
+    pdfium::span<const uint8_t> sample_data =
+        func->GetSampleStream()->GetSpan();
+    CFX_BitStream bitstream(sample_data);
+    for (uint32_t i = 0; i < sample_count; ++i) {
+      float float_colors[3];
+      for (uint32_t j = 0; j < 3; ++j) {
+        float sample = static_cast<float>(bitstream.GetBits(sample_size));
+        float interp = sample / (sample_count - 1);
+        float_colors[j] =
+            colors_min[j] + (colors_max[j] - colors_min[j]) * interp;
+      }
+      colors.push_back(SkPackARGB32NoCheck(0xFF, FloatToByte(float_colors[0]),
+                                           FloatToByte(float_colors[1]),
+                                           FloatToByte(float_colors[2])));
+      pos.push_back(static_cast<float>(i) / (sample_count - 1));
+    }
+  });
   return true;
 }
 
@@ -399,8 +397,9 @@
 
 // see https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
 SkScalar LineSide(const SkPoint line[2], const SkPoint& pt) {
-  return (line[1].fY - line[0].fY) * pt.fX - (line[1].fX - line[0].fX) * pt.fY +
-         line[1].fX * line[0].fY - line[1].fY * line[0].fX;
+  return UNSAFE_TODO((line[1].fY - line[0].fY) * pt.fX -
+                     (line[1].fX - line[0].fX) * pt.fY +
+                     line[1].fX * line[0].fY - line[1].fY * line[0].fX);
 }
 
 SkPoint IntersectSides(const SkPoint& parallelPt,
@@ -430,74 +429,83 @@
   SkScalar maxPerpDist = SK_ScalarMin;
   int minPerpPtIndex = -1;
   int maxPerpPtIndex = -1;
-  SkVector slope = pts[1] - pts[0];
-  SkPoint startPerp[2] = {pts[0], {pts[0].fX + slope.fY, pts[0].fY - slope.fX}};
-  SkPoint endPerp[2] = {pts[1], {pts[1].fX + slope.fY, pts[1].fY - slope.fX}};
-  for (int i = 0; i < 4; ++i) {
-    SkScalar sDist = LineSide(startPerp, rectPts[i]);
-    SkScalar eDist = LineSide(endPerp, rectPts[i]);
-    if (sDist * eDist <= 0)  // if the signs are different,
-      continue;              // the point is inside the gradient
-    if (sDist < 0) {
-      SkScalar smaller = std::min(sDist, eDist);
-      if (minPerpDist > smaller) {
-        minPerpDist = smaller;
-        minPerpPtIndex = i;
+  UNSAFE_TODO({
+    SkVector slope = pts[1] - pts[0];
+    SkPoint startPerp[2] = {pts[0],
+                            {pts[0].fX + slope.fY, pts[0].fY - slope.fX}};
+    SkPoint endPerp[2] = {pts[1], {pts[1].fX + slope.fY, pts[1].fY - slope.fX}};
+    for (int i = 0; i < 4; ++i) {
+      SkScalar sDist = LineSide(startPerp, rectPts[i]);
+      SkScalar eDist = LineSide(endPerp, rectPts[i]);
+      if (sDist * eDist <= 0) {  // if the signs are different,
+        continue;                // the point is inside the gradient
       }
-    } else {
-      SkScalar larger = std::max(sDist, eDist);
-      if (maxPerpDist < larger) {
-        maxPerpDist = larger;
-        maxPerpPtIndex = i;
+      if (sDist < 0) {
+        SkScalar smaller = std::min(sDist, eDist);
+        if (minPerpDist > smaller) {
+          minPerpDist = smaller;
+          minPerpPtIndex = i;
+        }
+      } else {
+        SkScalar larger = std::max(sDist, eDist);
+        if (maxPerpDist < larger) {
+          maxPerpDist = larger;
+          maxPerpPtIndex = i;
+        }
       }
     }
-  }
-  if (minPerpPtIndex < 0 && maxPerpPtIndex < 0)  // nothing's outside
-    return;
-
-  // determine if negative distances are before start or after end
-  SkPoint beforeStart = {pts[0].fX * 2 - pts[1].fX, pts[0].fY * 2 - pts[1].fY};
-  bool beforeNeg = LineSide(startPerp, beforeStart) < 0;
-
-  int noClipStartIndex = maxPerpPtIndex;
-  int noClipEndIndex = minPerpPtIndex;
-  if (beforeNeg)
-    std::swap(noClipStartIndex, noClipEndIndex);
-  if ((!clipStart && noClipStartIndex < 0) ||
-      (!clipEnd && noClipEndIndex < 0)) {
-    return;
-  }
-
-  const SkPoint& startEdgePt = clipStart ? pts[0] : rectPts[noClipStartIndex];
-  const SkPoint& endEdgePt = clipEnd ? pts[1] : rectPts[noClipEndIndex];
-
-  // find the corners that bound the gradient
-  SkScalar minDist = SK_ScalarMax;
-  SkScalar maxDist = SK_ScalarMin;
-  int minBounds = -1;
-  int maxBounds = -1;
-  for (int i = 0; i < 4; ++i) {
-    SkScalar dist = LineSide(pts, rectPts[i]);
-    if (minDist > dist) {
-      minDist = dist;
-      minBounds = i;
+    if (minPerpPtIndex < 0 && maxPerpPtIndex < 0) {  // nothing's outside
+      return;
     }
-    if (maxDist < dist) {
-      maxDist = dist;
-      maxBounds = i;
+
+    // determine if negative distances are before start or after end
+    SkPoint beforeStart = {pts[0].fX * 2 - pts[1].fX,
+                           pts[0].fY * 2 - pts[1].fY};
+    bool beforeNeg = LineSide(startPerp, beforeStart) < 0;
+
+    int noClipStartIndex = maxPerpPtIndex;
+    int noClipEndIndex = minPerpPtIndex;
+    if (beforeNeg) {
+      std::swap(noClipStartIndex, noClipEndIndex);
     }
-  }
-  if (minBounds < 0 || maxBounds < 0)
-    return;
-  if (minBounds == maxBounds)
-    return;
-  // construct a clip parallel to the gradient that goes through
-  // rectPts[minBounds] and rectPts[maxBounds] and perpendicular to the
-  // gradient that goes through startEdgePt, endEdgePt.
-  clip->moveTo(IntersectSides(rectPts[minBounds], slope, startEdgePt));
-  clip->lineTo(IntersectSides(rectPts[minBounds], slope, endEdgePt));
-  clip->lineTo(IntersectSides(rectPts[maxBounds], slope, endEdgePt));
-  clip->lineTo(IntersectSides(rectPts[maxBounds], slope, startEdgePt));
+    if ((!clipStart && noClipStartIndex < 0) ||
+        (!clipEnd && noClipEndIndex < 0)) {
+      return;
+    }
+
+    const SkPoint& startEdgePt = clipStart ? pts[0] : rectPts[noClipStartIndex];
+    const SkPoint& endEdgePt = clipEnd ? pts[1] : rectPts[noClipEndIndex];
+
+    // find the corners that bound the gradient
+    SkScalar minDist = SK_ScalarMax;
+    SkScalar maxDist = SK_ScalarMin;
+    int minBounds = -1;
+    int maxBounds = -1;
+    for (int i = 0; i < 4; ++i) {
+      SkScalar dist = LineSide(pts, rectPts[i]);
+      if (minDist > dist) {
+        minDist = dist;
+        minBounds = i;
+      }
+      if (maxDist < dist) {
+        maxDist = dist;
+        maxBounds = i;
+      }
+    }
+    if (minBounds < 0 || maxBounds < 0) {
+      return;
+    }
+    if (minBounds == maxBounds) {
+      return;
+    }
+    // construct a clip parallel to the gradient that goes through
+    // rectPts[minBounds] and rectPts[maxBounds] and perpendicular to the
+    // gradient that goes through startEdgePt, endEdgePt.
+    clip->moveTo(IntersectSides(rectPts[minBounds], slope, startEdgePt));
+    clip->lineTo(IntersectSides(rectPts[minBounds], slope, endEdgePt));
+    clip->lineTo(IntersectSides(rectPts[maxBounds], slope, endEdgePt));
+    clip->lineTo(IntersectSides(rectPts[maxBounds], slope, startEdgePt));
+  });
 }
 
 // Converts a stroking path to scanlines
@@ -1313,35 +1321,37 @@
     if (!skClip.isEmpty())
       m_pCanvas->clipPath(skClip, SkClipOp::kIntersect, true);
     m_pCanvas->concat(skMatrix);
-    while (!stream.IsEOF()) {
-      uint32_t flag = stream.ReadFlag();
-      size_t start_point = flag ? 4 : 0;
-      size_t start_color = flag ? 2 : 0;
-      if (flag) {
-        SkPoint temp_cubics[4];
-        for (size_t i = 0; i < std::size(temp_cubics); ++i) {
-          temp_cubics[i] = cubics[(flag * 3 + i) % 12];
+    UNSAFE_TODO({
+      while (!stream.IsEOF()) {
+        uint32_t flag = stream.ReadFlag();
+        size_t start_point = flag ? 4 : 0;
+        size_t start_color = flag ? 2 : 0;
+        if (flag) {
+          SkPoint temp_cubics[4];
+          for (size_t i = 0; i < std::size(temp_cubics); ++i) {
+            temp_cubics[i] = cubics[(flag * 3 + i) % 12];
+          }
+          std::copy(std::begin(temp_cubics), std::end(temp_cubics),
+                    std::begin(cubics));
+          SkColor temp_colors[2] = {colors[flag % 4], colors[(flag + 1) % 4]};
+          std::copy(std::begin(temp_colors), std::end(temp_colors),
+                    std::begin(colors));
         }
-        std::copy(std::begin(temp_cubics), std::end(temp_cubics),
-                  std::begin(cubics));
-        SkColor temp_colors[2] = {colors[flag % 4], colors[(flag + 1) % 4]};
-        std::copy(std::begin(temp_colors), std::end(temp_colors),
-                  std::begin(colors));
+        for (size_t i = start_point; i < std::size(cubics); ++i) {
+          CFX_PointF point = stream.ReadCoords();
+          cubics[i].fX = point.x;
+          cubics[i].fY = point.y;
+        }
+        for (size_t i = start_color; i < std::size(colors); ++i) {
+          FX_RGB_STRUCT<float> rgb = stream.ReadColor();
+          colors[i] =
+              SkColorSetARGB(0xFF, (U8CPU)(rgb.red * 255),
+                             (U8CPU)(rgb.green * 255), (U8CPU)(rgb.blue * 255));
+        }
+        m_pCanvas->drawPatch(cubics, colors, /*texCoords=*/nullptr,
+                             SkBlendMode::kDst, paint);
       }
-      for (size_t i = start_point; i < std::size(cubics); ++i) {
-        CFX_PointF point = stream.ReadCoords();
-        cubics[i].fX = point.x;
-        cubics[i].fY = point.y;
-      }
-      for (size_t i = start_color; i < std::size(colors); ++i) {
-        FX_RGB_STRUCT<float> rgb = stream.ReadColor();
-        colors[i] =
-            SkColorSetARGB(0xFF, (U8CPU)(rgb.red * 255),
-                           (U8CPU)(rgb.green * 255), (U8CPU)(rgb.blue * 255));
-      }
-      m_pCanvas->drawPatch(cubics, colors, /*texCoords=*/nullptr,
-                           SkBlendMode::kDst, paint);
-    }
+    });
     return true;
   }
   SkAutoCanvasRestore scoped_save_restore(m_pCanvas, /*doSave=*/true);