Prevent integer overflows in outline_aa::render_line().

Bug: chromium:1335110
Change-Id: I7bcaeb91525e66caed664bc5b685e38b3e65dd6a
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/94310
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/third_party/agg23/0014-ubsan-render-line.patch b/third_party/agg23/0014-ubsan-render-line.patch
new file mode 100644
index 0000000..b766eb2
--- /dev/null
+++ b/third_party/agg23/0014-ubsan-render-line.patch
@@ -0,0 +1,35 @@
+diff --git a/third_party/agg23/agg_rasterizer_scanline_aa.cpp b/third_party/agg23/agg_rasterizer_scanline_aa.cpp
+index d2b6a46e4..2f19a1816 100644
+--- a/third_party/agg23/agg_rasterizer_scanline_aa.cpp
++++ b/third_party/agg23/agg_rasterizer_scanline_aa.cpp
+@@ -227,10 +227,27 @@ AGG_INLINE void outline_aa::render_hline(int ey, int x1, int y1, int x2, int y2)
+ void outline_aa::render_line(int x1, int y1, int x2, int y2)
+ {
+     enum dx_limit_e { dx_limit = 16384 << poly_base_shift };
+-    int dx = x2 - x1;
++    pdfium::base::CheckedNumeric<int> safe_dx = x2;
++    safe_dx -= x1;
++    if (!safe_dx.IsValid())
++        return;
++
++    int dx = safe_dx.ValueOrDie();
+     if(dx >= dx_limit || dx <= -dx_limit) {
+-        int cx = (x1 + x2) >> 1;
+-        int cy = (y1 + y2) >> 1;
++        pdfium::base::CheckedNumeric<int> safe_cx = x1;
++        safe_cx += x2;
++        safe_cx /= 2;
++        if (!safe_cx.IsValid())
++            return;
++
++        pdfium::base::CheckedNumeric<int> safe_cy = y1;
++        safe_cy += y2;
++        safe_cy /= 2;
++        if (!safe_cy.IsValid())
++            return;
++
++        int cx = safe_cx.ValueOrDie();
++        int cy = safe_cy.ValueOrDie();
+         render_line(x1, y1, cx, cy);
+         render_line(cx, cy, x2, y2);
+     }
diff --git a/third_party/agg23/README.pdfium b/third_party/agg23/README.pdfium
index c372941..1b83932 100644
--- a/third_party/agg23/README.pdfium
+++ b/third_party/agg23/README.pdfium
@@ -30,3 +30,5 @@
 0011-path-storage-move-ctor.patch: Add a move ctor for path_storage.
 0012-infinite-loop.patch: Fix an infinite loop in calc_dash_start().
 0013-cxx20.patch: C++20 support.
+0014-ubsan-render-line.patch: Fix some integer overflows in
+outline_aa::render_line().
diff --git a/third_party/agg23/agg_rasterizer_scanline_aa.cpp b/third_party/agg23/agg_rasterizer_scanline_aa.cpp
index d2b6a46..392f302 100644
--- a/third_party/agg23/agg_rasterizer_scanline_aa.cpp
+++ b/third_party/agg23/agg_rasterizer_scanline_aa.cpp
@@ -227,10 +227,27 @@
 void outline_aa::render_line(int x1, int y1, int x2, int y2)
 {
     enum dx_limit_e { dx_limit = 16384 << poly_base_shift };
-    int dx = x2 - x1;
+    pdfium::base::CheckedNumeric<int> safe_dx = x2;
+    safe_dx -= x1;
+    if (!safe_dx.IsValid())
+        return;
+
+    int dx = safe_dx.ValueOrDie();
     if(dx >= dx_limit || dx <= -dx_limit) {
-        int cx = (x1 + x2) >> 1;
-        int cy = (y1 + y2) >> 1;
+        pdfium::base::CheckedNumeric<int> safe_cx = x1;
+        safe_cx += x2;
+        safe_cx /= 2;
+        if (!safe_cx.IsValid())
+            return;
+
+        pdfium::base::CheckedNumeric<int> safe_cy = y1;
+        safe_cy += y2;
+        safe_cy /= 2;
+        if (!safe_cy.IsValid())
+            return;
+
+        int cx = safe_cx.ValueOrDie();
+        int cy = safe_cy.ValueOrDie();
         render_line(x1, y1, cx, cy);
         render_line(cx, cy, x2, y2);
     }