Use CheckedNumerics to calculate size in CalculatePitchAndSize().
In CFX_DIBitmap::CalculatePitchAndSize(), instead of manually avoiding
integer overflow when calculating the pitch, use CheckedNumerics instead
by instantiating a FX_SAFE_UINT32.
This raises the limit for the maximum possible size.
Bug: chromium:1124660
Change-Id: Ib9ec3f68db1d8e78c7d893758f0ec1ceaf6cfe28
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/73398
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxge/dib/cfx_dibitmap.cpp b/core/fxge/dib/cfx_dibitmap.cpp
index 8a9c56e..587dac3 100644
--- a/core/fxge/dib/cfx_dibitmap.cpp
+++ b/core/fxge/dib/cfx_dibitmap.cpp
@@ -866,11 +866,12 @@
actual_pitch = safe_pitch.ValueOrDie();
}
- if ((1 << 30) / actual_pitch < static_cast<uint32_t>(height))
+ FX_SAFE_UINT32 safe_size = actual_pitch;
+ safe_size *= height;
+ if (!safe_size.IsValid())
return pdfium::nullopt;
- uint32_t size = actual_pitch * static_cast<uint32_t>(height);
- return PitchAndSize{actual_pitch, size};
+ return PitchAndSize{actual_pitch, safe_size.ValueOrDie()};
}
bool CFX_DIBitmap::CompositeBitmap(int dest_left,
diff --git a/core/fxge/dib/cfx_dibitmap_unittest.cpp b/core/fxge/dib/cfx_dibitmap_unittest.cpp
index 507fdbe..08d5ad9 100644
--- a/core/fxge/dib/cfx_dibitmap_unittest.cpp
+++ b/core/fxge/dib/cfx_dibitmap_unittest.cpp
@@ -68,8 +68,8 @@
CFX_DIBitmap::CalculatePitchAndSize(4194304, 1024, FXDIB_8bppRgb, 0));
// Overflow cases with provided pitch.
- EXPECT_FALSE(CFX_DIBitmap::CalculatePitchAndSize(1073741825, 1, FXDIB_Argb,
- 1073741825));
+ EXPECT_FALSE(CFX_DIBitmap::CalculatePitchAndSize(2147484000u, 1, FXDIB_Argb,
+ 2147484000u));
EXPECT_FALSE(
CFX_DIBitmap::CalculatePitchAndSize(1048576, 1024, FXDIB_Argb, 4194304));
EXPECT_FALSE(CFX_DIBitmap::CalculatePitchAndSize(4194304, 1024, FXDIB_8bppRgb,
@@ -79,18 +79,18 @@
TEST(CFX_DIBitmap, CalculatePitchAndSizeBoundary) {
// Test boundary condition for pitch overflow.
Optional<CFX_DIBitmap::PitchAndSize> result =
- CFX_DIBitmap::CalculatePitchAndSize(268435456, 4, FXDIB_8bppRgb, 0);
+ CFX_DIBitmap::CalculatePitchAndSize(536870908, 4, FXDIB_8bppRgb, 0);
ASSERT_TRUE(result);
- EXPECT_EQ(268435456u, result.value().pitch);
- EXPECT_EQ(1073741824u, result.value().size);
+ EXPECT_EQ(536870908u, result.value().pitch);
+ EXPECT_EQ(2147483632u, result.value().size);
EXPECT_FALSE(
- CFX_DIBitmap::CalculatePitchAndSize(268435457, 4, FXDIB_8bppRgb, 0));
+ CFX_DIBitmap::CalculatePitchAndSize(536870909, 4, FXDIB_8bppRgb, 0));
// Test boundary condition for size overflow.
- result = CFX_DIBitmap::CalculatePitchAndSize(17043520, 63, FXDIB_8bppRgb, 0);
+ result = CFX_DIBitmap::CalculatePitchAndSize(68174084, 63, FXDIB_8bppRgb, 0);
ASSERT_TRUE(result);
- EXPECT_EQ(17043520u, result.value().pitch);
- EXPECT_EQ(1073741760u, result.value().size);
+ EXPECT_EQ(68174084u, result.value().pitch);
+ EXPECT_EQ(4294967292u, result.value().size);
EXPECT_FALSE(
- CFX_DIBitmap::CalculatePitchAndSize(17043521, 63, FXDIB_8bppRgb, 0));
+ CFX_DIBitmap::CalculatePitchAndSize(68174085, 63, FXDIB_8bppRgb, 0));
}