Add bounds checks to CWeightTable::Calc() and friends.

BUG=624514

Review-Url: https://codereview.chromium.org/2204773003
diff --git a/core/fxge/dib/dib_int.h b/core/fxge/dib/dib_int.h
index 61533ba..aa4a792 100644
--- a/core/fxge/dib/dib_int.h
+++ b/core/fxge/dib/dib_int.h
@@ -40,25 +40,27 @@
   int m_SrcEnd;
   int m_Weights[1];
 };
+
 class CWeightTable {
  public:
-  CWeightTable() { m_pWeightTables = nullptr; }
-  ~CWeightTable() {
-    FX_Free(m_pWeightTables);
-    m_pWeightTables = nullptr;
-  }
-  void Calc(int dest_len,
+  CWeightTable();
+  ~CWeightTable();
+
+  bool Calc(int dest_len,
             int dest_min,
             int dest_max,
             int src_len,
             int src_min,
             int src_max,
             int flags);
-  PixelWeight* GetPixelWeight(int pixel) {
-    return (PixelWeight*)(m_pWeightTables + (pixel - m_DestMin) * m_ItemSize);
-  }
-  int m_DestMin, m_ItemSize;
+  PixelWeight* GetPixelWeight(int pixel) const;
+  int* GetValueFromPixelWeight(PixelWeight* pWeight, int index) const;
+
+ private:
+  int m_DestMin;
+  int m_ItemSize;
   uint8_t* m_pWeightTables;
+  size_t m_dwWeightTablesSize;
 };
 
 class CStretchEngine {
diff --git a/core/fxge/dib/fx_dib_engine.cpp b/core/fxge/dib/fx_dib_engine.cpp
index 1b80ed4..697bbb7 100644
--- a/core/fxge/dib/fx_dib_engine.cpp
+++ b/core/fxge/dib/fx_dib_engine.cpp
@@ -32,7 +32,17 @@
 
 }  // namespace
 
-void CWeightTable::Calc(int dest_len,
+CWeightTable::CWeightTable()
+    : m_DestMin(0),
+      m_ItemSize(0),
+      m_pWeightTables(nullptr),
+      m_dwWeightTablesSize(0) {}
+
+CWeightTable::~CWeightTable() {
+  FX_Free(m_pWeightTables);
+}
+
+bool CWeightTable::Calc(int dest_len,
                         int dest_min,
                         int dest_max,
                         int src_len,
@@ -41,26 +51,22 @@
                         int flags) {
   FX_Free(m_pWeightTables);
   m_pWeightTables = nullptr;
-  double scale, base;
-  scale = (FX_FLOAT)src_len / (FX_FLOAT)dest_len;
-  if (dest_len < 0) {
-    base = (FX_FLOAT)(src_len);
-  } else {
-    base = 0;
-  }
-  int ext_size = flags & FXDIB_BICUBIC_INTERPOL ? 3 : 1;
+  m_dwWeightTablesSize = 0;
+  const double scale = (FX_FLOAT)src_len / (FX_FLOAT)dest_len;
+  const double base = dest_len < 0 ? (FX_FLOAT)(src_len) : 0;
+  const int ext_size = flags & FXDIB_BICUBIC_INTERPOL ? 3 : 1;
   m_ItemSize =
       sizeof(int) * 2 +
       (int)(sizeof(int) * (FXSYS_ceil(FXSYS_fabs((FX_FLOAT)scale)) + ext_size));
   m_DestMin = dest_min;
-  if ((dest_max - dest_min) > (int)((1U << 30) - 4) / m_ItemSize) {
-    return;
-  }
-  m_pWeightTables =
-      FX_TryAlloc(uint8_t, (dest_max - dest_min) * m_ItemSize + 4);
-  if (!m_pWeightTables) {
-    return;
-  }
+  if ((dest_max - dest_min) > (int)((1U << 30) - 4) / m_ItemSize)
+    return false;
+
+  m_dwWeightTablesSize = (dest_max - dest_min) * m_ItemSize + 4;
+  m_pWeightTables = FX_TryAlloc(uint8_t, m_dwWeightTablesSize);
+  if (!m_pWeightTables)
+    return false;
+
   if ((flags & FXDIB_NOSMOOTH) != 0 || FXSYS_fabs((FX_FLOAT)scale) < 1.0f) {
     for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) {
       PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel);
@@ -179,8 +185,9 @@
         pixel_weights.m_Weights[0] = 65536;
       }
     }
-    return;
+    return true;
   }
+
   for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) {
     PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel);
     double src_start = dest_pixel * scale + base;
@@ -228,10 +235,28 @@
         pixel_weights.m_SrcEnd--;
         break;
       }
-      pixel_weights.m_Weights[j - start_i] =
-          FXSYS_round((FX_FLOAT)(weight * 65536));
+      size_t idx = j - start_i;
+      if (idx >= m_dwWeightTablesSize)
+        return false;
+      pixel_weights.m_Weights[idx] = FXSYS_round((FX_FLOAT)(weight * 65536));
     }
   }
+  return true;
+}
+
+PixelWeight* CWeightTable::GetPixelWeight(int pixel) const {
+  ASSERT(pixel >= m_DestMin);
+  return reinterpret_cast<PixelWeight*>(m_pWeightTables +
+                                        (pixel - m_DestMin) * m_ItemSize);
+}
+
+int* CWeightTable::GetValueFromPixelWeight(PixelWeight* pWeight,
+                                           int index) const {
+  if (index < pWeight->m_SrcStart)
+    return nullptr;
+
+  size_t idx = index - pWeight->m_SrcStart;
+  return idx < m_dwWeightTablesSize ? &pWeight->m_Weights[idx] : nullptr;
 }
 
 CStretchEngine::CStretchEngine(IFX_ScanlineComposer* pDestBitmap,
@@ -385,9 +410,10 @@
     if (!m_pDestMaskScanline)
       return FALSE;
   }
-  m_WeightTable.Calc(m_DestWidth, m_DestClip.left, m_DestClip.right, m_SrcWidth,
-                     m_SrcClip.left, m_SrcClip.right, m_Flags);
-  if (!m_WeightTable.m_pWeightTables)
+  bool ret =
+      m_WeightTable.Calc(m_DestWidth, m_DestClip.left, m_DestClip.right,
+                         m_SrcWidth, m_SrcClip.left, m_SrcClip.right, m_Flags);
+  if (!ret)
     return FALSE;
 
   m_CurRow = m_SrcClip.top;
@@ -431,8 +457,12 @@
           int dest_a = 0;
           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
                j++) {
-            int pixel_weight =
-                pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+            int* pWeight =
+                m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j);
+            if (!pWeight)
+              return FALSE;
+
+            int pixel_weight = *pWeight;
             if (src_scan[j / 8] & (1 << (7 - j % 8))) {
               dest_a += pixel_weight * 255;
             }
@@ -450,8 +480,12 @@
           int dest_a = 0;
           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
                j++) {
-            int pixel_weight =
-                pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+            int* pWeight =
+                m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j);
+            if (!pWeight)
+              return FALSE;
+
+            int pixel_weight = *pWeight;
             dest_a += pixel_weight * src_scan[j];
           }
           if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
@@ -467,8 +501,12 @@
           int dest_a = 0, dest_r = 0;
           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
                j++) {
-            int pixel_weight =
-                pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+            int* pWeight =
+                m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j);
+            if (!pWeight)
+              return FALSE;
+
+            int pixel_weight = *pWeight;
             pixel_weight = pixel_weight * src_scan_mask[j] / 255;
             dest_r += pixel_weight * src_scan[j];
             dest_a += pixel_weight;
@@ -488,8 +526,12 @@
           int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0;
           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
                j++) {
-            int pixel_weight =
-                pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+            int* pWeight =
+                m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j);
+            if (!pWeight)
+              return FALSE;
+
+            int pixel_weight = *pWeight;
             unsigned long argb_cmyk = m_pSrcPalette[src_scan[j]];
             if (m_DestFormat == FXDIB_Rgb) {
               dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >> 16);
@@ -521,8 +563,12 @@
           int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0;
           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
                j++) {
-            int pixel_weight =
-                pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+            int* pWeight =
+                m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j);
+            if (!pWeight)
+              return FALSE;
+
+            int pixel_weight = *pWeight;
             pixel_weight = pixel_weight * src_scan_mask[j] / 255;
             unsigned long argb_cmyk = m_pSrcPalette[src_scan[j]];
             if (m_DestFormat == FXDIB_Rgba) {
@@ -558,8 +604,12 @@
           int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0;
           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
                j++) {
-            int pixel_weight =
-                pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+            int* pWeight =
+                m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j);
+            if (!pWeight)
+              return FALSE;
+
+            int pixel_weight = *pWeight;
             const uint8_t* src_pixel = src_scan + j * Bpp;
             dest_b_c += pixel_weight * (*src_pixel++);
             dest_g_m += pixel_weight * (*src_pixel++);
@@ -586,8 +636,12 @@
           int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0;
           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
                j++) {
-            int pixel_weight =
-                pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+            int* pWeight =
+                m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j);
+            if (!pWeight)
+              return FALSE;
+
+            int pixel_weight = *pWeight;
             const uint8_t* src_pixel = src_scan + j * Bpp;
             if (m_DestFormat == FXDIB_Argb) {
               pixel_weight = pixel_weight * src_pixel[3] / 255;
@@ -632,15 +686,15 @@
     return;
 
   CWeightTable table;
-  table.Calc(m_DestHeight, m_DestClip.top, m_DestClip.bottom, m_SrcHeight,
-             m_SrcClip.top, m_SrcClip.bottom, m_Flags);
-  if (!table.m_pWeightTables)
+  bool ret = table.Calc(m_DestHeight, m_DestClip.top, m_DestClip.bottom,
+                        m_SrcHeight, m_SrcClip.top, m_SrcClip.bottom, m_Flags);
+  if (!ret)
     return;
 
-  int DestBpp = m_DestBpp / 8;
+  const int DestBpp = m_DestBpp / 8;
   for (int row = m_DestClip.top; row < m_DestClip.bottom; row++) {
     unsigned char* dest_scan = m_pDestScanline;
-    unsigned char* dest_sacn_mask = m_pDestMaskScanline;
+    unsigned char* dest_scan_mask = m_pDestMaskScanline;
     PixelWeight* pPixelWeights = table.GetPixelWeight(row);
     switch (m_TransMethod) {
       case 1:
@@ -652,8 +706,11 @@
           int dest_a = 0;
           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
                j++) {
-            int pixel_weight =
-                pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+            int* pWeight = table.GetValueFromPixelWeight(pPixelWeights, j);
+            if (!pWeight)
+              return;
+
+            int pixel_weight = *pWeight;
             dest_a +=
                 pixel_weight * src_scan[(j - m_SrcClip.top) * m_InterPitch];
           }
@@ -674,8 +731,11 @@
           int dest_a = 0, dest_k = 0;
           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
                j++) {
-            int pixel_weight =
-                pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+            int* pWeight = table.GetValueFromPixelWeight(pPixelWeights, j);
+            if (!pWeight)
+              return;
+
+            int pixel_weight = *pWeight;
             dest_k +=
                 pixel_weight * src_scan[(j - m_SrcClip.top) * m_InterPitch];
             dest_a += pixel_weight *
@@ -687,7 +747,7 @@
           }
           *dest_scan = (uint8_t)(dest_k >> 16);
           dest_scan += DestBpp;
-          *dest_sacn_mask++ = (uint8_t)(dest_a >> 16);
+          *dest_scan_mask++ = (uint8_t)(dest_a >> 16);
         }
         break;
       }
@@ -699,8 +759,11 @@
           int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0;
           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
                j++) {
-            int pixel_weight =
-                pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+            int* pWeight = table.GetValueFromPixelWeight(pPixelWeights, j);
+            if (!pWeight)
+              return;
+
+            int pixel_weight = *pWeight;
             const uint8_t* src_pixel =
                 src_scan + (j - m_SrcClip.top) * m_InterPitch;
             dest_b_c += pixel_weight * (*src_pixel++);
@@ -734,8 +797,11 @@
           int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0;
           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
                j++) {
-            int pixel_weight =
-                pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+            int* pWeight = table.GetValueFromPixelWeight(pPixelWeights, j);
+            if (!pWeight)
+              return;
+
+            int pixel_weight = *pWeight;
             const uint8_t* src_pixel =
                 src_scan + (j - m_SrcClip.top) * m_InterPitch;
             int mask_v = 255;
@@ -771,11 +837,11 @@
           if (m_DestFormat == FXDIB_Argb) {
             dest_scan[3] = (uint8_t)((dest_a) >> 16);
           } else {
-            *dest_sacn_mask = (uint8_t)((dest_a) >> 16);
+            *dest_scan_mask = (uint8_t)((dest_a) >> 16);
           }
           dest_scan += DestBpp;
-          if (dest_sacn_mask) {
-            dest_sacn_mask++;
+          if (dest_scan_mask) {
+            dest_scan_mask++;
           }
         }
         break;