Introduce more span<> in fxfa.

Avoid some pointer arithmetic warnings in general.
Introduce a few more bounds checks and reorder existing ones.
Use size_t where possible.

Disassembly shows the optimizer has removed the need for
any int3/ud2 bad bounds traps from these functions.

Change-Id: I77203d0580ac0f7d89deadb0a773294aca28af67
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/52610
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/xfa/fxfa/cxfa_textparser.cpp b/xfa/fxfa/cxfa_textparser.cpp
index 84ad724..d989f2c 100644
--- a/xfa/fxfa/cxfa_textparser.cpp
+++ b/xfa/fxfa/cxfa_textparser.cpp
@@ -283,9 +283,7 @@
       0xb182eaae,  // body
       0xdb8ac455,  // html
   };
-  static const int32_t s_iCount = FX_ArraySize(s_XFATagName);
-
-  return std::binary_search(s_XFATagName, s_XFATagName + s_iCount,
+  return std::binary_search(std::begin(s_XFATagName), std::end(s_XFATagName),
                             FX_HashCode_GetW(wsName.AsStringView(), true));
 }
 
diff --git a/xfa/fxfa/parser/cxfa_localevalue.cpp b/xfa/fxfa/parser/cxfa_localevalue.cpp
index fe62e81..047ead8 100644
--- a/xfa/fxfa/parser/cxfa_localevalue.cpp
+++ b/xfa/fxfa/parser/cxfa_localevalue.cpp
@@ -369,60 +369,62 @@
   static const uint16_t wCountY = 4;
   static const uint16_t wCountM = 2;
   static const uint16_t wCountD = 2;
-  int nLen = wsDate.GetLength();
-  if (nLen < wCountY || nLen > wCountY + wCountM + wCountD + 2)
+  pdfium::span<const wchar_t> spDate = wsDate.AsSpan();
+  if (spDate.size() < wCountY ||
+      spDate.size() > wCountY + wCountM + wCountD + 2) {
     return false;
-
+  }
   const bool bSymbol = wsDate.Contains(0x2D);
   uint16_t wYear = 0;
   uint16_t wMonth = 0;
   uint16_t wDay = 0;
-  const wchar_t* pDate = wsDate.c_str();
-  int nIndex = 0;
-  int nStart = 0;
-  while (pDate[nIndex] != '\0' && nIndex < wCountY) {
-    if (!FXSYS_IsDecimalDigit(pDate[nIndex]))
+  size_t nIndex = 0;
+  size_t nStart = 0;
+  while (nIndex < wCountY && spDate[nIndex] != '\0') {
+    if (!FXSYS_IsDecimalDigit(spDate[nIndex]))
       return false;
 
-    wYear = (pDate[nIndex] - '0') + wYear * 10;
+    wYear = (spDate[nIndex] - '0') + wYear * 10;
     nIndex++;
   }
   if (bSymbol) {
-    if (pDate[nIndex] != 0x2D)
+    if (nIndex >= spDate.size() || spDate[nIndex] != 0x2D)
       return false;
     nIndex++;
   }
 
   nStart = nIndex;
-  while (pDate[nIndex] != '\0' && nIndex - nStart < wCountM && nIndex < nLen) {
-    if (!FXSYS_IsDecimalDigit(pDate[nIndex]))
+  while (nIndex < spDate.size() && spDate[nIndex] != '\0' &&
+         nIndex - nStart < wCountM) {
+    if (!FXSYS_IsDecimalDigit(spDate[nIndex]))
       return false;
 
-    wMonth = (pDate[nIndex] - '0') + wMonth * 10;
+    wMonth = (spDate[nIndex] - '0') + wMonth * 10;
     nIndex++;
   }
   if (bSymbol) {
-    if (pDate[nIndex] != 0x2D)
+    if (nIndex >= spDate.size() || spDate[nIndex] != 0x2D)
       return false;
     nIndex++;
   }
 
   nStart = nIndex;
-  while (pDate[nIndex] != '\0' && nIndex - nStart < wCountD && nIndex < nLen) {
-    if (!FXSYS_IsDecimalDigit(pDate[nIndex]))
+  while (nIndex < spDate.size() && spDate[nIndex] != '\0' &&
+         nIndex - nStart < wCountD) {
+    if (!FXSYS_IsDecimalDigit(spDate[nIndex]))
       return false;
 
-    wDay = (pDate[nIndex] - '0') + wDay * 10;
+    wDay = (spDate[nIndex] - '0') + wDay * 10;
     nIndex++;
   }
-  if (nIndex != nLen)
+  if (nIndex != spDate.size())
     return false;
   if (wYear < 1900 || wYear > 2029)
     return false;
   if (wMonth < 1 || wMonth > 12)
-    return wMonth == 0 && nLen == wCountY;
+    return wMonth == 0 && spDate.size() == wCountY;
   if (wDay < 1)
-    return wDay == 0 && (nLen == wCountY + wCountM);
+    return wDay == 0 && spDate.size() == wCountY + wCountM;
   if (wMonth == 2) {
     if (wYear % 400 == 0 || (wYear % 100 != 0 && wYear % 4 == 0)) {
       if (wDay > 29)
@@ -440,8 +442,8 @@
 }
 
 bool CXFA_LocaleValue::ValidateCanonicalTime(const WideString& wsTime) {
-  int nLen = wsTime.GetLength();
-  if (nLen < 2)
+  pdfium::span<const wchar_t> spTime = wsTime.AsSpan();
+  if (spTime.size() < 2)
     return false;
 
   const uint16_t wCountH = 2;
@@ -453,85 +455,89 @@
   uint16_t wMinute = 0;
   uint16_t wSecond = 0;
   uint16_t wFraction = 0;
-  const wchar_t* pTime = wsTime.c_str();
-  int nIndex = 0;
-  int nStart = 0;
-  while (nIndex - nStart < wCountH && pTime[nIndex]) {
-    if (!FXSYS_IsDecimalDigit(pTime[nIndex]))
+  size_t nIndex = 0;
+  size_t nStart = 0;
+  while (nIndex - nStart < wCountH && spTime[nIndex]) {
+    if (!FXSYS_IsDecimalDigit(spTime[nIndex]))
       return false;
-    wHour = pTime[nIndex] - '0' + wHour * 10;
+    wHour = spTime[nIndex] - '0' + wHour * 10;
     nIndex++;
   }
   if (bSymbol) {
-    if (nIndex < nLen && pTime[nIndex] != ':')
+    if (nIndex < spTime.size() && spTime[nIndex] != ':')
       return false;
     nIndex++;
   }
 
   nStart = nIndex;
-  while (nIndex - nStart < wCountM && nIndex < nLen && pTime[nIndex]) {
-    if (!FXSYS_IsDecimalDigit(pTime[nIndex]))
+  while (nIndex < spTime.size() && spTime[nIndex] != '\0' &&
+         nIndex - nStart < wCountM) {
+    if (!FXSYS_IsDecimalDigit(spTime[nIndex]))
       return false;
-    wMinute = pTime[nIndex] - '0' + wMinute * 10;
+    wMinute = spTime[nIndex] - '0' + wMinute * 10;
     nIndex++;
   }
   if (bSymbol) {
-    if (nIndex < nLen && pTime[nIndex] != ':')
+    if (nIndex >= spTime.size() || spTime[nIndex] != ':')
       return false;
     nIndex++;
   }
   nStart = nIndex;
-  while (nIndex - nStart < wCountS && nIndex < nLen && pTime[nIndex]) {
-    if (!FXSYS_IsDecimalDigit(pTime[nIndex]))
+  while (nIndex < spTime.size() && spTime[nIndex] != '\0' &&
+         nIndex - nStart < wCountS) {
+    if (!FXSYS_IsDecimalDigit(spTime[nIndex]))
       return false;
-    wSecond = pTime[nIndex] - '0' + wSecond * 10;
+    wSecond = spTime[nIndex] - '0' + wSecond * 10;
     nIndex++;
   }
   auto pos = wsTime.Find('.');
   if (pos.has_value() && pos.value() != 0) {
-    if (pTime[nIndex] != '.')
+    if (nIndex >= spTime.size() || spTime[nIndex] != '.')
       return false;
     nIndex++;
     nStart = nIndex;
-    while (nIndex - nStart < wCountF && nIndex < nLen && pTime[nIndex]) {
-      if (!FXSYS_IsDecimalDigit(pTime[nIndex]))
+    while (nIndex < spTime.size() && spTime[nIndex] != '\0' &&
+           nIndex - nStart < wCountF) {
+      if (!FXSYS_IsDecimalDigit(spTime[nIndex]))
         return false;
-      wFraction = pTime[nIndex] - '0' + wFraction * 10;
+      wFraction = spTime[nIndex] - '0' + wFraction * 10;
       nIndex++;
     }
   }
-  if (nIndex < nLen) {
-    if (pTime[nIndex] == 'Z') {
+  if (nIndex < spTime.size()) {
+    if (spTime[nIndex] == 'Z') {
       nIndex++;
-    } else if (pTime[nIndex] == '-' || pTime[nIndex] == '+') {
+    } else if (spTime[nIndex] == '-' || spTime[nIndex] == '+') {
       int16_t nOffsetH = 0;
       int16_t nOffsetM = 0;
       nIndex++;
       nStart = nIndex;
-      while (nIndex - nStart < wCountH && nIndex < nLen && pTime[nIndex]) {
-        if (!FXSYS_IsDecimalDigit(pTime[nIndex]))
+      while (nIndex < spTime.size() && spTime[nIndex] != '\0' &&
+             nIndex - nStart < wCountH) {
+        if (!FXSYS_IsDecimalDigit(spTime[nIndex]))
           return false;
-        nOffsetH = pTime[nIndex] - '0' + nOffsetH * 10;
+        nOffsetH = spTime[nIndex] - '0' + nOffsetH * 10;
         nIndex++;
       }
       if (bSymbol) {
-        if (nIndex < nLen && pTime[nIndex] != ':')
+        if (nIndex >= spTime.size() || spTime[nIndex] != ':')
           return false;
         nIndex++;
       }
       nStart = nIndex;
-      while (nIndex - nStart < wCountM && nIndex < nLen && pTime[nIndex]) {
-        if (!FXSYS_IsDecimalDigit(pTime[nIndex]))
+      while (nIndex < spTime.size() && spTime[nIndex] != '\0' &&
+             nIndex - nStart < wCountM) {
+        if (!FXSYS_IsDecimalDigit(spTime[nIndex]))
           return false;
-        nOffsetM = pTime[nIndex] - '0' + nOffsetM * 10;
+        nOffsetM = spTime[nIndex] - '0' + nOffsetM * 10;
         nIndex++;
       }
       if (nOffsetH > 12 || nOffsetM >= 60)
         return false;
     }
   }
-  return nIndex == nLen && wHour < 24 && wMinute < 60 && wSecond < 60 &&
-         wFraction <= 999;
+  return nIndex == spTime.size() && wHour < 24 && wMinute < 60 &&
+         wSecond < 60 && wFraction <= 999;
 }
 
 bool CXFA_LocaleValue::ParsePatternValue(const WideString& wsValue,
@@ -652,12 +658,12 @@
   if (wsFormat.IsEmpty() || wsNumeric.IsEmpty())
     return true;
 
-  const wchar_t* pNum = wsNumeric.c_str();
-  const wchar_t* pFmt = wsFormat.c_str();
+  pdfium::span<const wchar_t> spNum = wsNumeric.AsSpan();
+  pdfium::span<const wchar_t> spFmt = wsFormat.AsSpan();
   int32_t n = 0;
   int32_t nf = 0;
-  wchar_t c = pNum[n];
-  wchar_t cf = pFmt[nf];
+  wchar_t c = spNum[n];
+  wchar_t cf = spFmt[nf];
   if (cf == L's') {
     if (c == L'-' || c == L'+')
       ++n;
@@ -668,9 +674,9 @@
   int32_t nCount = wsNumeric.GetLength();
   int32_t nCountFmt = wsFormat.GetLength();
   while (n < nCount && (bLimit ? nf < nCountFmt : true) &&
-         FXSYS_IsDecimalDigit(c = pNum[n])) {
+         FXSYS_IsDecimalDigit(c = spNum[n])) {
     if (bLimit == true) {
-      if ((cf = pFmt[nf]) == L'*')
+      if ((cf = spFmt[nf]) == L'*')
         bLimit = false;
       else if (cf == L'z')
         nf++;
@@ -684,7 +690,7 @@
   if (nf == nCountFmt)
     return false;
 
-  while (nf < nCountFmt && (cf = pFmt[nf]) != L'.') {
+  while (nf < nCountFmt && (cf = spFmt[nf]) != L'.') {
     ASSERT(cf == L'z' || cf == L'*');
     ++nf;
   }
@@ -695,7 +701,7 @@
   else
     wsDecimalSymbol = WideString(L'.');
 
-  if (pFmt[nf] != L'.')
+  if (spFmt[nf] != L'.')
     return false;
   if (wsDecimalSymbol != WideStringView(c) && c != L'.')
     return false;
@@ -703,10 +709,10 @@
   ++nf;
   ++n;
   bLimit = true;
-  while (n < nCount && (bLimit ? nf < nCountFmt : true) &&
-         FXSYS_IsDecimalDigit(c = pNum[n])) {
-    if (bLimit == true) {
-      if ((cf = pFmt[nf]) == L'*')
+  while (n < nCount && (!bLimit || nf < nCountFmt) &&
+         FXSYS_IsDecimalDigit(spNum[n])) {
+    if (bLimit) {
+      if ((cf = spFmt[nf]) == L'*')
         bLimit = false;
       else if (cf == L'z')
         nf++;
diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp
index 9f19a49..7a1d1fe 100644
--- a/xfa/fxfa/parser/cxfa_node.cpp
+++ b/xfa/fxfa/parser/cxfa_node.cpp
@@ -381,18 +381,13 @@
     49,  50,  51,  255, 255, 255, 255, 255,
 };
 
-uint8_t* XFA_RemoveBase64Whitespace(const uint8_t* pStr, int32_t iLen) {
-  uint8_t* pCP;
-  int32_t i = 0, j = 0;
-  if (iLen == 0) {
-    iLen = strlen((char*)pStr);
-  }
-  pCP = FX_Alloc(uint8_t, iLen + 1);
-  for (; i < iLen; i++) {
-    if ((pStr[i] & 128) == 0) {
-      if (g_inv_base64[pStr[i]] != 0xFF || pStr[i] == '=') {
-        pCP[j++] = pStr[i];
-      }
+uint8_t* XFA_RemoveBase64Whitespace(pdfium::span<const uint8_t> spStr) {
+  uint8_t* pCP = FX_Alloc(uint8_t, spStr.size() + 1);
+  size_t j = 0;
+  for (size_t i = 0; i < spStr.size(); ++i) {
+    if ((spStr[i] & 128) == 0 &&
+        (g_inv_base64[spStr[i]] != 0xFF || spStr[i] == '=')) {
+      pCP[j++] = spStr[i];
     }
   }
   pCP[j] = '\0';
@@ -400,14 +395,11 @@
 }
 
 int32_t XFA_Base64Decode(const char* pStr, uint8_t* pOutBuffer) {
-  if (!pStr) {
+  if (!pStr)
     return 0;
-  }
-  uint8_t* pBuffer =
-      XFA_RemoveBase64Whitespace((uint8_t*)pStr, strlen((char*)pStr));
-  if (!pBuffer) {
-    return 0;
-  }
+
+  uint8_t* pBuffer = XFA_RemoveBase64Whitespace(
+      {reinterpret_cast<const uint8_t*>(pStr), strlen(pStr)});
   int32_t iLen = strlen((char*)pBuffer);
   int32_t i = 0, j = 0;
   uint32_t dwLimb = 0;