Add IndexInBounds() convenience routine.

Avoid writing |Type| in CollectionSize<Type>() so that index
type can change without rewriting conditions.

Change-Id: I40c94ca39148b379908760ba9b861114b88af7bb
Reviewed-on: https://pdfium-review.googlesource.com/3056
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_font.cpp b/core/fpdfapi/font/cpdf_font.cpp
index 7988ec7..f0b5ac1 100644
--- a/core/fpdfapi/font/cpdf_font.cpp
+++ b/core/fpdfapi/font/cpdf_font.cpp
@@ -458,10 +458,9 @@
 }
 
 int CPDF_Font::FallbackGlyphFromCharcode(int fallbackFont, uint32_t charcode) {
-  if (fallbackFont < 0 ||
-      fallbackFont >= pdfium::CollectionSize<int>(m_FontFallbacks)) {
+  if (!pdfium::IndexInBounds(m_FontFallbacks, fallbackFont))
     return -1;
-  }
+
   int glyph =
       FXFT_Get_Char_Index(m_FontFallbacks[fallbackFont]->GetFace(), charcode);
   if (glyph == 0 || glyph == 0xffff)
diff --git a/core/fpdfapi/font/ttgsubtable.cpp b/core/fpdfapi/font/ttgsubtable.cpp
index 946ccd7..4fae5d4 100644
--- a/core/fpdfapi/font/ttgsubtable.cpp
+++ b/core/fpdfapi/font/ttgsubtable.cpp
@@ -127,9 +127,8 @@
                                            uint32_t* vglyphnum,
                                            TFeature* Feature) {
   for (int index : Feature->LookupListIndices) {
-    if (index < 0 || index >= pdfium::CollectionSize<int>(LookupList.Lookups))
+    if (!pdfium::IndexInBounds(LookupList.Lookups, index))
       continue;
-
     if (LookupList.Lookups[index].LookupType == 1 &&
         GetVerticalGlyphSub2(glyphnum, vglyphnum, &LookupList.Lookups[index])) {
       return true;
@@ -154,8 +153,7 @@
       case 2: {
         auto* tbl2 = static_cast<TSingleSubstFormat2*>(subTable.get());
         int index = GetCoverageIndex(tbl2->Coverage.get(), glyphnum);
-        if (index >= 0 &&
-            index < pdfium::CollectionSize<int>(tbl2->Substitutes)) {
+        if (pdfium::IndexInBounds(tbl2->Substitutes, index)) {
           *vglyphnum = tbl2->Substitutes[index];
           return true;
         }
diff --git a/core/fpdfapi/page/cpdf_pageobjectlist.cpp b/core/fpdfapi/page/cpdf_pageobjectlist.cpp
index 02b590e..5c30fe9 100644
--- a/core/fpdfapi/page/cpdf_pageobjectlist.cpp
+++ b/core/fpdfapi/page/cpdf_pageobjectlist.cpp
@@ -10,7 +10,5 @@
 #include "third_party/base/stl_util.h"
 
 CPDF_PageObject* CPDF_PageObjectList::GetPageObjectByIndex(int index) {
-  if (index < 0 || index >= pdfium::CollectionSize<int>(*this))
-    return nullptr;
-  return (*this)[index].get();
+  return pdfium::IndexInBounds(*this, index) ? (*this)[index].get() : nullptr;
 }
diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp
index ed88a4f..8ff9e66 100644
--- a/core/fpdfapi/parser/cpdf_document.cpp
+++ b/core/fpdfapi/parser/cpdf_document.cpp
@@ -477,10 +477,10 @@
 }
 
 CPDF_Dictionary* CPDF_Document::GetPage(int iPage) {
-  if (iPage < 0 || iPage >= pdfium::CollectionSize<int>(m_PageList))
+  if (!pdfium::IndexInBounds(m_PageList, iPage))
     return nullptr;
 
-  if (m_bLinearized && (iPage == m_iFirstPageNo)) {
+  if (m_bLinearized && iPage == m_iFirstPageNo) {
     if (CPDF_Dictionary* pDict =
             ToDictionary(GetOrParseIndirectObject(m_dwFirstPageObjNum))) {
       return pDict;
@@ -586,7 +586,7 @@
   int found_index = FindPageIndex(pPages, &skip_count, objnum, &start_index);
 
   // Corrupt page tree may yield out-of-range results.
-  if (found_index < 0 || found_index >= pdfium::CollectionSize<int>(m_PageList))
+  if (!pdfium::IndexInBounds(m_PageList, found_index))
     return -1;
 
   m_PageList[found_index] = objnum;
diff --git a/core/fpdftext/cpdf_textpage.cpp b/core/fpdftext/cpdf_textpage.cpp
index 7a89b24..1eab19f 100644
--- a/core/fpdftext/cpdf_textpage.cpp
+++ b/core/fpdftext/cpdf_textpage.cpp
@@ -378,10 +378,7 @@
 }
 
 void CPDF_TextPage::GetCharInfo(int index, FPDF_CHAR_INFO* info) const {
-  if (!m_bIsParsed)
-    return;
-
-  if (index < 0 || index >= pdfium::CollectionSize<int>(m_CharList))
+  if (!m_bIsParsed || !pdfium::IndexInBounds(m_CharList, index))
     return;
 
   const PAGECHAR_INFO& charinfo = m_CharList[index];
@@ -496,10 +493,7 @@
                             float& top,
                             float& right,
                             float& bottom) const {
-  if (!m_bIsParsed)
-    return;
-
-  if (rectIndex < 0 || rectIndex >= pdfium::CollectionSize<int>(m_SelRects))
+  if (!m_bIsParsed || !pdfium::IndexInBounds(m_SelRects, rectIndex))
     return;
 
   left = m_SelRects[rectIndex].left;
diff --git a/core/fxcodec/lgif/fx_gif.cpp b/core/fxcodec/lgif/fx_gif.cpp
index c4661b0..c109b61 100644
--- a/core/fxcodec/lgif/fx_gif.cpp
+++ b/core/fxcodec/lgif/fx_gif.cpp
@@ -841,11 +841,11 @@
   gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA);
   return 1;
 }
+
 int32_t gif_load_frame(gif_decompress_struct_p gif_ptr, int32_t frame_num) {
-  if (!gif_ptr || frame_num < 0 ||
-      frame_num >= pdfium::CollectionSize<int>(*gif_ptr->img_ptr_arr_ptr)) {
+  if (!gif_ptr || !pdfium::IndexInBounds(*gif_ptr->img_ptr_arr_ptr, frame_num))
     return 0;
-  }
+
   uint8_t* data_size_ptr = nullptr;
   uint8_t* data_ptr = nullptr;
   uint32_t skip_size_org = gif_ptr->skip_size;
diff --git a/core/fxcrt/fx_arabic.cpp b/core/fxcrt/fx_arabic.cpp
index 103271c..76f2e38 100644
--- a/core/fxcrt/fx_arabic.cpp
+++ b/core/fxcrt/fx_arabic.cpp
@@ -415,9 +415,9 @@
   void FX_BidiReverseString(std::vector<CFX_Char>& chars,
                             int32_t iStart,
                             int32_t iCount) {
-    ASSERT(iStart >= 0 && iStart < pdfium::CollectionSize<int32_t>(chars));
-    ASSERT(iCount >= 0 &&
-           iStart + iCount <= pdfium::CollectionSize<int32_t>(chars));
+    ASSERT(pdfium::IndexInBounds(chars, iStart));
+    ASSERT(pdfium::IndexInBounds(chars, iCount));
+    ASSERT(iStart + iCount <= pdfium::CollectionSize<int32_t>(chars));
     std::reverse(chars.begin() + iStart, chars.begin() + iStart + iCount);
   }
 
@@ -426,7 +426,7 @@
                              int32_t iStart,
                              int32_t iCount,
                              int32_t iValue) {
-    ASSERT(iStart >= 0 && iStart <= pdfium::CollectionSize<int32_t>(chars));
+    ASSERT(pdfium::IndexInBounds(chars, iStart));
     ASSERT(iStart - iCount > -1);
     int32_t iLast = iStart - iCount;
     if (bClass) {
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
index 88c88a1..aaa0e98 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
@@ -172,10 +172,8 @@
     pPage->Release();
     return nullptr;
   }
-  if (page_index >= 0 &&
-      page_index < pdfium::CollectionSize<int>(m_XFAPageList)) {
+  if (pdfium::IndexInBounds(m_XFAPageList, page_index))
     m_XFAPageList[page_index] = pPage;
-  }
   return pPage;
 }
 
@@ -203,20 +201,17 @@
   if (m_pPDFDoc)
     m_pPDFDoc->DeletePage(page_index);
 
-  if (page_index < 0 ||
-      page_index >= pdfium::CollectionSize<int>(m_XFAPageList)) {
+  if (!pdfium::IndexInBounds(m_XFAPageList, page_index))
     return;
-  }
+
   if (CPDFXFA_Page* pPage = m_XFAPageList[page_index])
     pPage->Release();
 }
 
 void CPDFXFA_Context::RemovePage(CPDFXFA_Page* page) {
   int page_index = page->GetPageIndex();
-  if (page_index >= 0 &&
-      page_index < pdfium::CollectionSize<int>(m_XFAPageList)) {
+  if (pdfium::IndexInBounds(m_XFAPageList, page_index))
     m_XFAPageList[page_index] = nullptr;
-  }
 }
 
 void CPDFXFA_Context::ClearChangeMark() {
diff --git a/fpdfsdk/pdfwindow/PWL_FontMap.cpp b/fpdfsdk/pdfwindow/PWL_FontMap.cpp
index 9a2962c..a7c4269 100644
--- a/fpdfsdk/pdfwindow/PWL_FontMap.cpp
+++ b/fpdfsdk/pdfwindow/PWL_FontMap.cpp
@@ -55,32 +55,26 @@
       m_pPDFDoc->CreateNewDoc();
     }
   }
-
   return m_pPDFDoc.get();
 }
 
 CPDF_Font* CPWL_FontMap::GetPDFFont(int32_t nFontIndex) {
-  if (nFontIndex >= 0 && nFontIndex < pdfium::CollectionSize<int32_t>(m_Data)) {
-    if (m_Data[nFontIndex])
-      return m_Data[nFontIndex]->pFont;
-  }
+  if (pdfium::IndexInBounds(m_Data, nFontIndex) && m_Data[nFontIndex])
+    return m_Data[nFontIndex]->pFont;
+
   return nullptr;
 }
 
 CFX_ByteString CPWL_FontMap::GetPDFFontAlias(int32_t nFontIndex) {
-  if (nFontIndex >= 0 && nFontIndex < pdfium::CollectionSize<int32_t>(m_Data)) {
-    if (m_Data[nFontIndex])
-      return m_Data[nFontIndex]->sFontName;
-  }
+  if (pdfium::IndexInBounds(m_Data, nFontIndex) && m_Data[nFontIndex])
+    return m_Data[nFontIndex]->sFontName;
+
   return CFX_ByteString();
 }
 
 bool CPWL_FontMap::KnowWord(int32_t nFontIndex, uint16_t word) {
-  if (nFontIndex >= 0 && nFontIndex < pdfium::CollectionSize<int32_t>(m_Data)) {
-    if (m_Data[nFontIndex])
-      return CharCodeFromUnicode(nFontIndex, word) >= 0;
-  }
-  return false;
+  return pdfium::IndexInBounds(m_Data, nFontIndex) && m_Data[nFontIndex] &&
+         CharCodeFromUnicode(nFontIndex, word) >= 0;
 }
 
 int32_t CPWL_FontMap::GetWordFontIndex(uint16_t word,
@@ -116,7 +110,7 @@
 }
 
 int32_t CPWL_FontMap::CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) {
-  if (nFontIndex < 0 || nFontIndex >= pdfium::CollectionSize<int32_t>(m_Data))
+  if (!pdfium::IndexInBounds(m_Data, nFontIndex))
     return -1;
 
   CPWL_FontMap_Data* pData = m_Data[nFontIndex].get();
@@ -284,10 +278,7 @@
 }
 
 const CPWL_FontMap_Data* CPWL_FontMap::GetFontMapData(int32_t nIndex) const {
-  if (nIndex < 0 || nIndex >= pdfium::CollectionSize<int32_t>(m_Data))
-    return nullptr;
-
-  return m_Data[nIndex].get();
+  return pdfium::IndexInBounds(m_Data, nIndex) ? m_Data[nIndex].get() : nullptr;
 }
 
 int32_t CPWL_FontMap::GetNativeCharset() {
diff --git a/third_party/base/stl_util.h b/third_party/base/stl_util.h
index 795414b..96947f5 100644
--- a/third_party/base/stl_util.h
+++ b/third_party/base/stl_util.h
@@ -44,6 +44,13 @@
   return pdfium::base::checked_cast<ResultType>(collection.size());
 }
 
+// Convenience routine for "int-fected" code, to handle signed indicies. The
+// compiler can deduce the type, making this more convenient than the above.
+template <typename IndexType, typename Collection>
+bool IndexInBounds(const Collection& collection, IndexType index) {
+  return index >= 0 && index < CollectionSize<IndexType>(collection);
+}
+
 // Track the addition of an object to a set, removing it automatically when
 // the ScopedSetInsertion goes out of scope.
 template <typename T>
diff --git a/xfa/fde/tto/fde_textout.cpp b/xfa/fde/tto/fde_textout.cpp
index c9f5ec8..f816176 100644
--- a/xfa/fde/tto/fde_textout.cpp
+++ b/xfa/fde/tto/fde_textout.cpp
@@ -775,10 +775,7 @@
 }
 
 FDE_TTOPIECE* CFDE_TTOLine::GetPtrAt(int32_t index) {
-  if (index < 0 || index >= pdfium::CollectionSize<int32_t>(m_pieces))
-    return nullptr;
-
-  return &m_pieces[index];
+  return pdfium::IndexInBounds(m_pieces, index) ? &m_pieces[index] : nullptr;
 }
 
 void CFDE_TTOLine::RemoveLast(int32_t icount) {
diff --git a/xfa/fde/xml/fde_xml_imp.cpp b/xfa/fde/xml/fde_xml_imp.cpp
index 0959661..3344100 100644
--- a/xfa/fde/xml/fde_xml_imp.cpp
+++ b/xfa/fde/xml/fde_xml_imp.cpp
@@ -652,7 +652,7 @@
 }
 
 bool CFDE_XMLInstruction::GetData(int32_t index, CFX_WideString& wsData) const {
-  if (index < 0 || index >= pdfium::CollectionSize<int32_t>(m_TargetData))
+  if (!pdfium::IndexInBounds(m_TargetData, index))
     return false;
 
   wsData = m_TargetData[index];
@@ -664,10 +664,8 @@
 }
 
 void CFDE_XMLInstruction::RemoveData(int32_t index) {
-  if (index < 0 || index >= pdfium::CollectionSize<int32_t>(m_TargetData))
-    return;
-
-  m_TargetData.erase(m_TargetData.begin() + index);
+  if (pdfium::IndexInBounds(m_TargetData, index))
+    m_TargetData.erase(m_TargetData.begin() + index);
 }
 
 CFDE_XMLInstruction::~CFDE_XMLInstruction() {}
diff --git a/xfa/fgas/layout/cfx_breakline.cpp b/xfa/fgas/layout/cfx_breakline.cpp
index 65860e4..562f984 100644
--- a/xfa/fgas/layout/cfx_breakline.cpp
+++ b/xfa/fgas/layout/cfx_breakline.cpp
@@ -17,12 +17,12 @@
 }
 
 CFX_Char* CFX_BreakLine::GetChar(int32_t index) {
-  ASSERT(index >= 0 && index < pdfium::CollectionSize<int32_t>(m_LineChars));
+  ASSERT(pdfium::IndexInBounds(m_LineChars, index));
   return &m_LineChars[index];
 }
 
 const CFX_Char* CFX_BreakLine::GetChar(int32_t index) const {
-  ASSERT(index >= 0 && index < pdfium::CollectionSize<int32_t>(m_LineChars));
+  ASSERT(pdfium::IndexInBounds(m_LineChars, index));
   return &m_LineChars[index];
 }
 
diff --git a/xfa/fgas/layout/fgas_rtfbreak.cpp b/xfa/fgas/layout/fgas_rtfbreak.cpp
index 3782214..68c04a7 100644
--- a/xfa/fgas/layout/fgas_rtfbreak.cpp
+++ b/xfa/fgas/layout/fgas_rtfbreak.cpp
@@ -805,8 +805,9 @@
 
   const std::vector<CFX_BreakPiece>& pRTFPieces =
       m_RTFLine[m_iReadyLineIndex].m_LinePieces;
-  if (index < 0 || index >= pdfium::CollectionSize<int32_t>(pRTFPieces))
+  if (!pdfium::IndexInBounds(pRTFPieces, index))
     return nullptr;
+
   return &pRTFPieces[index];
 }
 
diff --git a/xfa/fgas/layout/fgas_textbreak.cpp b/xfa/fgas/layout/fgas_textbreak.cpp
index 8bba780..c42de45 100644
--- a/xfa/fgas/layout/fgas_textbreak.cpp
+++ b/xfa/fgas/layout/fgas_textbreak.cpp
@@ -796,11 +796,10 @@
 const CFX_BreakPiece* CFX_TxtBreak::GetBreakPiece(int32_t index) const {
   if (!HasTxtLine())
     return nullptr;
-  if (index < 0 ||
-      index >= pdfium::CollectionSize<int32_t>(
-                   m_TxtLine[m_iReadyLineIndex].m_LinePieces)) {
+
+  if (!pdfium::IndexInBounds(m_TxtLine[m_iReadyLineIndex].m_LinePieces, index))
     return nullptr;
-  }
+
   return &m_TxtLine[m_iReadyLineIndex].m_LinePieces[index];
 }