Avoid integer overflow in CPDF_ToUnicodeMap::HandleBeginBFRange()

In CPDF_ToUnicodeMap::HandleBeginBFRange(), there are 3 for-loops
which increase `code` values in the range between `lowcode` and
`highcode`. If `highcode` is 0xffffffff, the "code++" operation will
cause integer overflow and these for-loops will never be terminated.

Make `code` FX_SAFE_UINT32 type so that its value can be validated
for each for-loop to avoid integer overflow.

Bug: chromium:1343510
Change-Id: Icb8221ce026fade90b01151c6f675b9a4d3b2f2b
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/95310
Commit-Queue: Nigi <nigi@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_tounicodemap.cpp b/core/fpdfapi/font/cpdf_tounicodemap.cpp
index 4fa92bf..4ec5a3c 100644
--- a/core/fpdfapi/font/cpdf_tounicodemap.cpp
+++ b/core/fpdfapi/font/cpdf_tounicodemap.cpp
@@ -173,8 +173,10 @@
 
     ByteStringView start = pParser->GetWord();
     if (start == "[") {
-      for (uint32_t code = lowcode; code <= highcode; code++)
-        SetCode(code, StringToWideString(pParser->GetWord()));
+      for (FX_SAFE_UINT32 code = lowcode;
+           code.IsValid() && code.ValueOrDie() <= highcode; code++) {
+        SetCode(code.ValueOrDie(), StringToWideString(pParser->GetWord()));
+      }
       pParser->GetWord();
       continue;
     }
@@ -186,13 +188,17 @@
         return;
 
       uint32_t value = value_or_error.value();
-      for (uint32_t code = lowcode; code <= highcode; code++)
-        m_Multimap.emplace(code, value++);
+      for (FX_SAFE_UINT32 code = lowcode;
+           code.IsValid() && code.ValueOrDie() <= highcode; code++) {
+        m_Multimap.emplace(code.ValueOrDie(), value++);
+      }
     } else {
-      for (uint32_t code = lowcode; code <= highcode; code++) {
+      for (FX_SAFE_UINT32 code = lowcode;
+           code.IsValid() && code.ValueOrDie() <= highcode; code++) {
+        uint32_t code_value = code.ValueOrDie();
         WideString retcode =
-            code == lowcode ? destcode : StringDataAdd(destcode);
-        m_Multimap.emplace(code, GetMultiCharIndexIndicator());
+            code_value == lowcode ? destcode : StringDataAdd(destcode);
+        m_Multimap.emplace(code_value, GetMultiCharIndexIndicator());
         m_MultiCharVec.push_back(retcode);
         destcode = std::move(retcode);
       }
diff --git a/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp
index 7dacc5a..48e7c2f 100644
--- a/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp
+++ b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp
@@ -4,8 +4,11 @@
 
 #include "core/fpdfapi/font/cpdf_tounicodemap.h"
 
+#include "core/fpdfapi/parser/cpdf_stream.h"
+#include "core/fxcrt/retain_ptr.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/base/span.h"
 
 TEST(cpdf_tounicodemap, StringToCode) {
   EXPECT_THAT(CPDF_ToUnicodeMap::StringToCode("<0001>"), testing::Optional(1u));
@@ -47,3 +50,32 @@
   EXPECT_EQ(res, CPDF_ToUnicodeMap::StringToWideString("<c2abFaAb>"));
   EXPECT_EQ(res, CPDF_ToUnicodeMap::StringToWideString("<c2abFaAb12>"));
 }
+
+TEST(cpdf_tounicodemap, HandleBeginBFRangeAvoidIntegerOverflow) {
+  // Make sure there won't be infinite loops due to integer overflows in
+  // HandleBeginBFRange().
+  {
+    static constexpr uint8_t kInput1[] =
+        "beginbfrange<FFFFFFFF><FFFFFFFF>[<0041>]endbfrange";
+    auto stream = pdfium::MakeRetain<CPDF_Stream>();
+    stream->SetData(pdfium::make_span(kInput1));
+    CPDF_ToUnicodeMap map(stream.Get());
+    EXPECT_STREQ(L"A", map.Lookup(0xffffffff).c_str());
+  }
+  {
+    static constexpr uint8_t kInput2[] =
+        "beginbfrange<FFFFFFFF><FFFFFFFF><0042>endbfrange";
+    auto stream = pdfium::MakeRetain<CPDF_Stream>();
+    stream->SetData(pdfium::make_span(kInput2));
+    CPDF_ToUnicodeMap map(stream.Get());
+    EXPECT_STREQ(L"B", map.Lookup(0xffffffff).c_str());
+  }
+  {
+    static constexpr uint8_t kInput3[] =
+        "beginbfrange<FFFFFFFF><FFFFFFFF><00410042>endbfrange";
+    auto stream = pdfium::MakeRetain<CPDF_Stream>();
+    stream->SetData(pdfium::make_span(kInput3));
+    CPDF_ToUnicodeMap map(stream.Get());
+    EXPECT_STREQ(L"AB", map.Lookup(0xffffffff).c_str());
+  }
+}