Fix overly-strong ASSERT in WeightTable::SetStartEnd()

A zero-length range at zero represented by [0, -1]  will be fine so long
as we don't actually try to reference the range. Stop short of switching
over to the simpler [0, 0) representation. Note that `weight_count` is
bounded by earlier size checks and fits in an int.

-- Add another ASSERT to earlier tests.

Bug: chromium:1219974
Change-Id: I26b077d11e54465b861070e887b3efde8f2178da
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/82155
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxge/dib/cstretchengine.cpp b/core/fxge/dib/cstretchengine.cpp
index 69cb8db..5b2ff3b 100644
--- a/core/fxge/dib/cstretchengine.cpp
+++ b/core/fxge/dib/cstretchengine.cpp
@@ -35,6 +35,9 @@
 // static
 size_t CStretchEngine::PixelWeight::TotalBytesForWeightCount(
     size_t weight_count) {
+  // Always room for one weight even for empty ranges due to declaration
+  // of m_Weights[1] in the header. Don't shrink below this since
+  // CalculateWeights() relies on this later.
   const size_t extra_weights = weight_count > 0 ? weight_count - 1 : 0;
   FX_SAFE_SIZE_T total_bytes = extra_weights;
   total_bytes *= sizeof(m_Weights[0]);
@@ -95,7 +98,8 @@
         src_start = std::max(src_start, src_min);
         src_end = std::min(src_end, src_max - 1);
         pixel_weights.SetStartEnd(src_start, src_end, weight_count);
-        if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) {
+        if (pixel_weights.m_SrcStart >= pixel_weights.m_SrcEnd) {
+          // Always room for one weight per size calculation.
           pixel_weights.m_Weights[0] = kFixedPointOne;
         } else {
           pixel_weights.m_Weights[1] = FixedFromFloat(
diff --git a/core/fxge/dib/cstretchengine.h b/core/fxge/dib/cstretchengine.h
index 5ebebb4..eef7fd0 100644
--- a/core/fxge/dib/cstretchengine.h
+++ b/core/fxge/dib/cstretchengine.h
@@ -38,7 +38,7 @@
     static size_t TotalBytesForWeightCount(size_t weight_count);
 
     void SetStartEnd(int src_start, int src_end, size_t weight_count) {
-      CHECK_LT(static_cast<size_t>(src_end - src_start), weight_count);
+      CHECK_LT(src_end - src_start, static_cast<int>(weight_count));
       m_SrcStart = src_start;
       m_SrcEnd = src_end;
     }
@@ -61,7 +61,7 @@
     }
 
     int m_SrcStart;
-    int m_SrcEnd;           // Note: inclusive.
+    int m_SrcEnd;           // Note: inclusive, [0, -1] for empty range at 0.
     uint32_t m_Weights[1];  // Not really 1, variable size.
   };
 
diff --git a/core/fxge/dib/cstretchengine_unittest.cpp b/core/fxge/dib/cstretchengine_unittest.cpp
index 202db9f..a64024d 100644
--- a/core/fxge/dib/cstretchengine_unittest.cpp
+++ b/core/fxge/dib/cstretchengine_unittest.cpp
@@ -29,8 +29,8 @@
                            const FXDIB_ResampleOptions& options) {
   constexpr uint32_t kExpectedSum = CStretchEngine::kFixedPointOne;
   CStretchEngine::WeightTable table;
-  table.CalculateWeights(dest_width, 0, dest_width, src_width, 0, src_width,
-                         options);
+  ASSERT_TRUE(table.CalculateWeights(dest_width, 0, dest_width, src_width, 0,
+                                     src_width, options));
   for (uint32_t i = 0; i < dest_width; ++i) {
     EXPECT_EQ(kExpectedSum, PixelWeightSum(table.GetPixelWeight(i)))
         << "for { " << src_width << ", " << dest_width << " } at " << i;
@@ -92,3 +92,31 @@
   options.bInterpolateBilinear = true;
   ExecuteStretchTests(options);
 }
+
+TEST(CStretchEngine, ZeroLengthSrc) {
+  FXDIB_ResampleOptions options;
+  CStretchEngine::WeightTable table;
+  ASSERT_TRUE(table.CalculateWeights(100, 0, 100, 0, 0, 0, options));
+}
+
+TEST(CStretchEngine, ZeroLengthSrcNoSmoothing) {
+  FXDIB_ResampleOptions options;
+  options.bNoSmoothing = true;
+  CStretchEngine::WeightTable table;
+  ASSERT_TRUE(table.CalculateWeights(100, 0, 100, 0, 0, 0, options));
+}
+
+TEST(CStretchEngine, ZeroLengthSrcBilinear) {
+  FXDIB_ResampleOptions options;
+  options.bInterpolateBilinear = true;
+  CStretchEngine::WeightTable table;
+  ASSERT_TRUE(table.CalculateWeights(100, 0, 100, 0, 0, 0, options));
+}
+
+TEST(CStretchEngine, ZeroLengthSrcNoSmoothingBilinear) {
+  FXDIB_ResampleOptions options;
+  options.bNoSmoothing = true;
+  options.bInterpolateBilinear = true;
+  CStretchEngine::WeightTable table;
+  ASSERT_TRUE(table.CalculateWeights(100, 0, 100, 0, 0, 0, options));
+}