Consolidate UNSAFE_BUFFERS usage in fpdf_cmaps.cpp

Add helper functions to create spans for the CMaps data, to consolidate
all the UNSAFE_BUFFERS usage in this file.

Change-Id: I01f7a183940a02adb8c30fb9d14bf8864140bdcb
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/134572
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/cmaps/fpdf_cmaps.cpp b/core/fpdfapi/cmaps/fpdf_cmaps.cpp
index 7ba8435..35dc01d 100644
--- a/core/fpdfapi/cmaps/fpdf_cmaps.cpp
+++ b/core/fpdfapi/cmaps/fpdf_cmaps.cpp
@@ -26,6 +26,23 @@
   uint16_t cid;
 };
 
+pdfium::span<const SingleCmap> GetSingleCmapSpan(const CMap* cmap) {
+  // SAFETY: `CMap` uses manually audited constexpr data.
+  return UNSAFE_BUFFERS(pdfium::span(
+      reinterpret_cast<const SingleCmap*>(cmap->word_map_), cmap->word_count_));
+}
+
+pdfium::span<const RangeCmap> GetRangeCmapSpan(const CMap* cmap) {
+  // SAFETY: `CMap` uses manually audited constexpr data.
+  return UNSAFE_BUFFERS(pdfium::span(
+      reinterpret_cast<const RangeCmap*>(cmap->word_map_), cmap->word_count_));
+}
+
+pdfium::span<const DWordCIDMap> GetDWordCIDMapCmapSpan(const CMap* cmap) {
+  // SAFETY: `CMap` uses manually audited constexpr data.
+  return UNSAFE_BUFFERS(pdfium::span(cmap->dword_map_, cmap->dword_count_));
+}
+
 const CMap* FindNextCMap(const CMap* cmap) {
   if (cmap->use_offset_ == 0) {
     return nullptr;
@@ -39,11 +56,9 @@
   const uint16_t loword = static_cast<uint16_t>(charcode);
   while (cmap) {
     if (cmap->dword_map_) {
-      const DWordCIDMap* begin = cmap->dword_map_;
-      // SAFETY: `CMap` uses manually audited constexpr data.
-      const auto* end = UNSAFE_BUFFERS(begin + cmap->dword_count_);
+      auto dword_span = GetDWordCIDMapCmapSpan(cmap);
       const auto* found = std::lower_bound(
-          begin, end, charcode,
+          dword_span.begin(), dword_span.end(), charcode,
           [](const DWordCIDMap& element, uint32_t charcode) {
             uint16_t hiword = static_cast<uint16_t>(charcode >> 16);
             if (element.hi_word_ != hiword) {
@@ -51,7 +66,7 @@
             }
             return element.lo_word_high_ < static_cast<uint16_t>(charcode);
           });
-      if (found != end && loword >= found->lo_word_low_ &&
+      if (found != dword_span.end() && loword >= found->lo_word_low_ &&
           loword <= found->lo_word_high_) {
         return found->cid_ + loword - found->lo_word_low_;
       }
@@ -74,28 +89,26 @@
     CHECK(cmap->word_map_);
     switch (cmap->word_map_type_) {
       case CMap::Type::kSingle: {
-        const auto* begin =
-            reinterpret_cast<const SingleCmap*>(cmap->word_map_);
-        // SAFETY: `CMap` uses manually audited constexpr data.
-        const auto* end = UNSAFE_BUFFERS(begin + cmap->word_count_);
-        const auto* found = std::lower_bound(
-            begin, end, loword, [](const SingleCmap& element, uint16_t code) {
-              return element.code < code;
-            });
-        if (found != end && found->code == loword) {
+        auto single_span = GetSingleCmapSpan(cmap);
+        const auto* found =
+            std::lower_bound(single_span.begin(), single_span.end(), loword,
+                             [](const SingleCmap& element, uint16_t code) {
+                               return element.code < code;
+                             });
+        if (found != single_span.end() && found->code == loword) {
           return found->cid;
         }
         break;
       }
       case CMap::Type::kRange: {
-        const auto* begin = reinterpret_cast<const RangeCmap*>(cmap->word_map_);
-        // SAFETY: `CMap` uses manually audited constexpr data.
-        const auto* end = UNSAFE_BUFFERS(begin + cmap->word_count_);
-        const auto* found = std::lower_bound(
-            begin, end, loword, [](const RangeCmap& element, uint16_t code) {
-              return element.high < code;
-            });
-        if (found != end && loword >= found->low && loword <= found->high) {
+        auto range_span = GetRangeCmapSpan(cmap);
+        const auto* found =
+            std::lower_bound(range_span.begin(), range_span.end(), loword,
+                             [](const RangeCmap& element, uint16_t code) {
+                               return element.high < code;
+                             });
+        if (found != range_span.end() && loword >= found->low &&
+            loword <= found->high) {
           return found->cid + loword - found->low;
         }
         break;
@@ -118,11 +131,7 @@
   while (cmap) {
     switch (cmap->word_map_type_) {
       case CMap::Type::kSingle: {
-        // SAFETY: `CMap` uses manually audited constexpr data.
-        auto single_span = UNSAFE_BUFFERS(
-            pdfium::span(reinterpret_cast<const SingleCmap*>(cmap->word_map_),
-                         cmap->word_count_));
-        for (const auto& single : single_span) {
+        for (const auto& single : GetSingleCmapSpan(cmap)) {
           if (single.cid == cid) {
             return single.code;
           }
@@ -130,11 +139,7 @@
         break;
       }
       case CMap::Type::kRange: {
-        // SAFETY: `CMap` uses manually audited constexpr data.
-        auto range_span = UNSAFE_BUFFERS(
-            pdfium::span(reinterpret_cast<const RangeCmap*>(cmap->word_map_),
-                         cmap->word_count_));
-        for (const auto& range : range_span) {
+        for (const auto& range : GetRangeCmapSpan(cmap)) {
           if (cid >= range.cid && cid <= range.cid + range.high - range.low) {
             return range.low + cid - range.cid;
           }