[LTS] Prevent undefined behavior in CFX_DIBBase::GetOverlapRect().
Use FX_SAFE_INT32 to prevent integer overflows/underflows. Also mark the
method const.
Bug: chromium:1097499
Change-Id: Ie3809f0cb43cdf9558b40ec2a2e805f535ab749e
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/75410
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
(cherry picked from commit e03bf7b4af92edce27642b529982cd27b680a789)
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/77770
diff --git a/core/fxge/dib/cfx_dibbase.cpp b/core/fxge/dib/cfx_dibbase.cpp
index a2c1a9a..0b29b1f 100644
--- a/core/fxge/dib/cfx_dibbase.cpp
+++ b/core/fxge/dib/cfx_dibbase.cpp
@@ -879,47 +879,90 @@
int src_height,
int& src_left,
int& src_top,
- const CFX_ClipRgn* pClipRgn) {
+ const CFX_ClipRgn* pClipRgn) const {
if (width == 0 || height == 0)
return false;
ASSERT(width > 0);
ASSERT(height > 0);
- if (dest_left > m_Width || dest_top > m_Height) {
- width = 0;
- height = 0;
+ if (dest_left > m_Width || dest_top > m_Height)
return false;
- }
- int x_offset = dest_left - src_left;
- int y_offset = dest_top - src_top;
- FX_RECT src_rect(src_left, src_top, src_left + width, src_top + height);
+
+ FX_SAFE_INT32 safe_src_width = src_left;
+ safe_src_width += width;
+ if (!safe_src_width.IsValid())
+ return false;
+
+ FX_SAFE_INT32 safe_src_height = src_top;
+ safe_src_height += height;
+ if (!safe_src_height.IsValid())
+ return false;
+
+ FX_RECT src_rect(src_left, src_top, safe_src_width.ValueOrDie(),
+ safe_src_height.ValueOrDie());
FX_RECT src_bound(0, 0, src_width, src_height);
src_rect.Intersect(src_bound);
- FX_RECT dest_rect(src_rect.left + x_offset, src_rect.top + y_offset,
- src_rect.right + x_offset, src_rect.bottom + y_offset);
+
+ FX_SAFE_INT32 safe_x_offset = dest_left;
+ safe_x_offset -= src_left;
+ if (!safe_x_offset.IsValid())
+ return false;
+
+ FX_SAFE_INT32 safe_y_offset = dest_top;
+ safe_y_offset -= src_top;
+ if (!safe_y_offset.IsValid())
+ return false;
+
+ FX_SAFE_INT32 safe_dest_left = safe_x_offset;
+ safe_dest_left += src_rect.left;
+ if (!safe_dest_left.IsValid())
+ return false;
+
+ FX_SAFE_INT32 safe_dest_top = safe_y_offset;
+ safe_dest_top += src_rect.top;
+ if (!safe_dest_top.IsValid())
+ return false;
+
+ FX_SAFE_INT32 safe_dest_right = safe_x_offset;
+ safe_dest_right += src_rect.right;
+ if (!safe_dest_right.IsValid())
+ return false;
+
+ FX_SAFE_INT32 safe_dest_bottom = safe_y_offset;
+ safe_dest_bottom += src_rect.bottom;
+ if (!safe_dest_bottom.IsValid())
+ return false;
+
+ FX_RECT dest_rect(safe_dest_left.ValueOrDie(), safe_dest_top.ValueOrDie(),
+ safe_dest_right.ValueOrDie(),
+ safe_dest_bottom.ValueOrDie());
FX_RECT dest_bound(0, 0, m_Width, m_Height);
dest_rect.Intersect(dest_bound);
+
if (pClipRgn)
dest_rect.Intersect(pClipRgn->GetBox());
dest_left = dest_rect.left;
dest_top = dest_rect.top;
- FX_SAFE_INT32 safe_src_left = dest_left;
- safe_src_left -= x_offset;
- if (!safe_src_left.IsValid())
+ FX_SAFE_INT32 safe_new_src_left = dest_left;
+ safe_new_src_left -= safe_x_offset;
+ if (!safe_new_src_left.IsValid())
return false;
- src_left = safe_src_left.ValueOrDie();
+ src_left = safe_new_src_left.ValueOrDie();
- FX_SAFE_INT32 safe_src_top = dest_top;
- safe_src_top -= y_offset;
- if (!safe_src_top.IsValid())
+ FX_SAFE_INT32 safe_new_src_top = dest_top;
+ safe_new_src_top -= safe_y_offset;
+ if (!safe_new_src_top.IsValid())
return false;
- src_top = safe_src_top.ValueOrDie();
+ src_top = safe_new_src_top.ValueOrDie();
- width = dest_rect.right - dest_rect.left;
- height = dest_rect.bottom - dest_rect.top;
- return width != 0 && height != 0;
+ if (dest_rect.IsEmpty())
+ return false;
+
+ width = dest_rect.Width();
+ height = dest_rect.Height();
+ return true;
}
void CFX_DIBBase::SetPalette(const uint32_t* pSrc) {
diff --git a/core/fxge/dib/cfx_dibbase.h b/core/fxge/dib/cfx_dibbase.h
index a24e846..bf69ff2 100644
--- a/core/fxge/dib/cfx_dibbase.h
+++ b/core/fxge/dib/cfx_dibbase.h
@@ -97,7 +97,7 @@
int src_height,
int& src_left,
int& src_top,
- const CFX_ClipRgn* pClipRgn);
+ const CFX_ClipRgn* pClipRgn) const;
#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
void DebugVerifyBitmapIsPreMultiplied(void* buffer) const;