Spin in CFGAS_FormatString::ParseNum.

Consolidate increments of format string index at top of loop
to ensure progress is always made, rather than trying to do it
in every possible branch of the logic beneath it.

Bug: pdfium:1260
Change-Id: I2efeefcfd05ebec59350df4fe7ebec3d93f40426
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/51550
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/xfa/fgas/crt/cfgas_formatstring.cpp b/xfa/fgas/crt/cfgas_formatstring.cpp
index 925598c..b96203d 100644
--- a/xfa/fgas/crt/cfgas_formatstring.cpp
+++ b/xfa/fgas/crt/cfgas_formatstring.cpp
@@ -1366,9 +1366,8 @@
   if (dot_index < len && (dwFormatStyle & FX_NUMSTYLE_DotVorv))
     *wsValue += '.';
   if (!bReverseParse) {
-    ccf = dot_index_f + 1;
     cc = (dot_index == len) ? len : dot_index + 1;
-    while (cc < len && ccf < lenf) {
+    for (ccf = dot_index_f + 1; cc < len && ccf < lenf; ++ccf) {
       switch (strf[ccf]) {
         case '\'': {
           WideString wsLiteral = GetLiteralText(strf, &ccf, lenf);
@@ -1378,7 +1377,6 @@
             return false;
           }
           cc += iLiteralLen;
-          ccf++;
           break;
         }
         case '9':
@@ -1387,7 +1385,6 @@
 
           *wsValue += str[cc];
           cc++;
-          ccf++;
           break;
         case 'z':
         case 'Z':
@@ -1399,7 +1396,6 @@
           } else {
             cc++;
           }
-          ccf++;
           break;
         case 'S':
         case 's':
@@ -1413,7 +1409,6 @@
             bNeg = true;
             cc += iMinusLen;
           }
-          ccf++;
           break;
         case 'E': {
           if (cc >= len || (str[cc] != 'E' && str[cc] != 'e'))
@@ -1437,7 +1432,6 @@
             cc++;
           }
           iExponent = bExpSign ? -iExponent : iExponent;
-          ccf++;
           break;
         }
         case '$': {
@@ -1448,7 +1442,6 @@
             return false;
           }
           cc += iSymbolLen;
-          ccf++;
           break;
         }
         case 'c':
@@ -1461,7 +1454,7 @@
               bNeg = true;
               cc += 2;
             }
-            ccf += 2;
+            ccf++;
           }
           break;
         case 'd':
@@ -1474,7 +1467,7 @@
               bNeg = true;
               cc += 2;
             }
-            ccf += 2;
+            ccf++;
           }
           break;
         case '.':
@@ -1488,11 +1481,10 @@
               !wcsncmp(str + cc, wsSymbol.c_str(), iSysmbolLen)) {
             cc += iSysmbolLen;
           }
-          ccf++;
           bHavePercentSymbol = true;
         } break;
         case '8': {
-          while (ccf < lenf && strf[ccf] == '8')
+          while (ccf + 1 < lenf && strf[ccf + 1] == '8')
             ccf++;
 
           while (cc < len && FXSYS_IsDecimalDigit(str[cc])) {
@@ -1505,7 +1497,6 @@
               wcsncmp(str + cc, wsGroupSymbol.c_str(), iGroupLen) == 0) {
             cc += iGroupLen;
           }
-          ccf++;
           break;
         }
         case '(':
@@ -1516,14 +1507,12 @@
             return false;
 
           cc++;
-          ccf++;
           break;
         default:
           if (strf[ccf] != str[cc])
             return false;
 
           cc++;
-          ccf++;
       }
     }
     if (cc != len)
diff --git a/xfa/fgas/crt/cfgas_formatstring_unittest.cpp b/xfa/fgas/crt/cfgas_formatstring_unittest.cpp
index a3b7bd4..4cd24a2 100644
--- a/xfa/fgas/crt/cfgas_formatstring_unittest.cpp
+++ b/xfa/fgas/crt/cfgas_formatstring_unittest.cpp
@@ -417,6 +417,11 @@
       {L"en", L"123.545,4", L"zzz.zzz,z", L"123.5454"},
   };
 
+  static const TestCase failures[] = {
+      // https://crbug.com/pdfium/1260
+      {L"en", L"..", L"VC", L"."},
+  };
+
   for (const auto& test : tests) {
     WideString result;
     EXPECT_TRUE(fmt(test.locale)->ParseNum(test.input, test.pattern, &result))
@@ -424,6 +429,12 @@
     EXPECT_STREQ(test.output, result.c_str())
         << " TEST: " << test.input << ", " << test.pattern;
   }
+
+  for (const auto& test : failures) {
+    WideString result;
+    EXPECT_FALSE(fmt(test.locale)->ParseNum(test.input, test.pattern, &result))
+        << " TEST: " << test.input << ", " << test.pattern;
+  }
 }
 
 TEST_F(CFGAS_FormatStringTest, NumFormat) {