From 19cdfe4d73370b21709aefd9dce06cf463239fa1 Mon Sep 17 00:00:00 2001 From: thestig Date: Mon, 15 Aug 2016 14:33:21 -0700 Subject: Avoid integer overflows in FXGE_GetGlyphsBBox(). And also CFX_RenderDevice::DrawNormalText(). BUG=637192 Review-Url: https://codereview.chromium.org/2244613002 --- core/fxge/ge/cfx_renderdevice.cpp | 37 +++++++++++++++++++----- core/fxge/ge/fx_ge_text.cpp | 61 +++++++++++++++++++++++++++------------ 2 files changed, 71 insertions(+), 27 deletions(-) diff --git a/core/fxge/ge/cfx_renderdevice.cpp b/core/fxge/ge/cfx_renderdevice.cpp index 53ee039cd3..fcb99f79c2 100644 --- a/core/fxge/ge/cfx_renderdevice.cpp +++ b/core/fxge/ge/cfx_renderdevice.cpp @@ -6,6 +6,7 @@ #include "core/fxge/include/cfx_renderdevice.h" +#include "core/fxcrt/include/fx_safe_types.h" #include "core/fxge/include/cfx_fxgedevice.h" #include "core/fxge/include/cfx_graphstatedata.h" #include "core/fxge/include/cfx_pathdata.h" @@ -997,17 +998,30 @@ FX_BOOL CFX_RenderDevice::DrawNormalText(int nChars, int b = 0; if (anti_alias == FXFT_RENDER_MODE_LCD) ArgbDecode(fill_color, a, r, g, b); + for (const FXTEXT_GLYPHPOS& glyph : glyphs) { if (!glyph.m_pGlyph) continue; + + pdfium::base::CheckedNumeric left = glyph.m_OriginX; + left += glyph.m_pGlyph->m_Left; + left -= pixel_left; + if (!left.IsValid()) + return FALSE; + + pdfium::base::CheckedNumeric top = glyph.m_OriginY; + top -= glyph.m_pGlyph->m_Top; + top -= pixel_top; + if (!top.IsValid()) + return FALSE; + const CFX_DIBitmap* pGlyph = &glyph.m_pGlyph->m_Bitmap; - int left = glyph.m_OriginX + glyph.m_pGlyph->m_Left - pixel_left; - int top = glyph.m_OriginY - glyph.m_pGlyph->m_Top - pixel_top; int ncols = pGlyph->GetWidth(); int nrows = pGlyph->GetHeight(); if (anti_alias == FXFT_RENDER_MODE_NORMAL) { - if (!bitmap.CompositeMask(left, top, ncols, nrows, pGlyph, fill_color, 0, - 0, FXDIB_BLEND_NORMAL, nullptr, FALSE, 0, + if (!bitmap.CompositeMask(left.ValueOrDie(), top.ValueOrDie(), ncols, + nrows, pGlyph, fill_color, 0, 0, + FXDIB_BLEND_NORMAL, nullptr, FALSE, 0, nullptr)) { return FALSE; } @@ -1016,12 +1030,19 @@ FX_BOOL CFX_RenderDevice::DrawNormalText(int nChars, bool bBGRStripe = !!(text_flags & FXTEXT_BGR_STRIPE); ncols /= 3; int x_subpixel = (int)(glyph.m_fOriginX * 3) % 3; - int start_col = std::max(left, 0); - int end_col = std::min(left + ncols, dest_width); + int start_col = std::max(left.ValueOrDie(), 0); + pdfium::base::CheckedNumeric end_col_safe = left; + end_col_safe += ncols; + if (!end_col_safe.IsValid()) + return FALSE; + + int end_col = std::min(end_col_safe.ValueOrDie(), dest_width); if (start_col >= end_col) continue; - DrawNormalTextHelper(&bitmap, pGlyph, nrows, left, top, start_col, end_col, - bNormal, bBGRStripe, x_subpixel, a, r, g, b); + + DrawNormalTextHelper(&bitmap, pGlyph, nrows, left.ValueOrDie(), + top.ValueOrDie(), start_col, end_col, bNormal, + bBGRStripe, x_subpixel, a, r, g, b); } if (bitmap.IsAlphaMask()) SetBitMask(&bitmap, bmp_rect.left, bmp_rect.top, fill_color); diff --git a/core/fxge/ge/fx_ge_text.cpp b/core/fxge/ge/fx_ge_text.cpp index ac110b0291..5fea141a42 100644 --- a/core/fxge/ge/fx_ge_text.cpp +++ b/core/fxge/ge/fx_ge_text.cpp @@ -8,6 +8,7 @@ #include #include "core/fxcodec/include/fx_codec.h" +#include "core/fxcrt/include/fx_safe_types.h" #include "core/fxge/ge/fx_text_int.h" #include "core/fxge/include/cfx_fontmgr.h" #include "core/fxge/include/cfx_gemodule.h" @@ -58,27 +59,49 @@ FX_RECT FXGE_GetGlyphsBBox(const std::vector& glyphs, if (!pGlyph) continue; - int char_left = glyph.m_OriginX + pGlyph->m_Left; - int char_width = (int)(pGlyph->m_Bitmap.GetWidth() / retinaScaleX); - if (anti_alias == FXFT_RENDER_MODE_LCD) { + FX_SAFE_INT32 char_left = glyph.m_OriginX; + char_left += pGlyph->m_Left; + if (!char_left.IsValid()) + continue; + + FX_SAFE_INT32 char_width = pGlyph->m_Bitmap.GetWidth(); + char_width /= retinaScaleX; + if (anti_alias == FXFT_RENDER_MODE_LCD) char_width /= 3; + if (!char_width.IsValid()) + continue; + + FX_SAFE_INT32 char_right = char_left + char_width; + if (!char_right.IsValid()) + continue; + + FX_SAFE_INT32 char_top = glyph.m_OriginY; + char_top -= pGlyph->m_Top; + if (!char_top.IsValid()) + continue; + + FX_SAFE_INT32 char_height = pGlyph->m_Bitmap.GetHeight(); + char_height /= retinaScaleY; + if (!char_height.IsValid()) + continue; + + FX_SAFE_INT32 char_bottom = char_top + char_height; + if (!char_bottom.IsValid()) + continue; + + if (bStarted) { + rect.left = std::min(rect.left, char_left.ValueOrDie()); + rect.right = std::max(rect.right, char_right.ValueOrDie()); + rect.top = std::min(rect.top, char_top.ValueOrDie()); + rect.bottom = std::max(rect.bottom, char_bottom.ValueOrDie()); + continue; } - int char_right = char_left + char_width; - int char_top = glyph.m_OriginY - pGlyph->m_Top; - int char_bottom = - char_top + (int)(pGlyph->m_Bitmap.GetHeight() / retinaScaleY); - if (!bStarted) { - rect.left = char_left; - rect.right = char_right; - rect.top = char_top; - rect.bottom = char_bottom; - bStarted = true; - } else { - rect.left = std::min(rect.left, char_left); - rect.right = std::max(rect.right, char_right); - rect.top = std::min(rect.top, char_top); - rect.bottom = std::max(rect.bottom, char_bottom); - } + + rect.left = char_left.ValueOrDie(); + rect.right = char_right.ValueOrDie(); + rect.top = char_top.ValueOrDie(); + rect.bottom = char_bottom.ValueOrDie(); + bStarted = true; } return rect; } -- cgit v1.2.3