Resolve unsafe buffer issues in CFX_CTTGSubTable

Complete partial spanification effort.

Bug: pdfium:2155
Change-Id: Ib126fd47ab043c6b187f0f54083bcdbe5c38d00e
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/119111
Reviewed-by: Thomas Sepez <tsepez@google.com>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/font/cfx_cttgsubtable.cpp b/core/fpdfapi/font/cfx_cttgsubtable.cpp
index f70b497..80c512d 100644
--- a/core/fpdfapi/font/cfx_cttgsubtable.cpp
+++ b/core/fpdfapi/font/cfx_cttgsubtable.cpp
@@ -4,11 +4,6 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
-#if defined(UNSAFE_BUFFERS_BUILD)
-// TODO(crbug.com/pdfium/2153): resolve buffer safety issues.
-#pragma allow_unsafe_buffers
-#endif
-
 #include "core/fpdfapi/font/cfx_cttgsubtable.h"
 
 #include <stdint.h>
@@ -23,11 +18,8 @@
 namespace {
 
 bool IsVerticalFeatureTag(uint32_t tag) {
-  static constexpr uint32_t kTags[] = {
-      CFX_FontMapper::MakeTag('v', 'r', 't', '2'),
-      CFX_FontMapper::MakeTag('v', 'e', 'r', 't'),
-  };
-  return tag == kTags[0] || tag == kTags[1];
+  return tag == CFX_FontMapper::MakeTag('v', 'r', 't', '2') ||
+         tag == CFX_FontMapper::MakeTag('v', 'e', 'r', 't');
 }
 
 }  // namespace
@@ -157,37 +149,33 @@
   return -1;
 }
 
-uint8_t CFX_CTTGSUBTable::GetUInt8(const uint8_t*& p) const {
-  uint8_t ret = p[0];
-  p += 1;
+uint8_t CFX_CTTGSUBTable::GetUInt8(pdfium::span<const uint8_t>& p) const {
+  uint8_t ret = p.front();
+  p = p.subspan(1u);
   return ret;
 }
 
-int16_t CFX_CTTGSUBTable::GetInt16(const uint8_t*& p) const {
-  // TODO(tsepez): pass actual span.
-  uint16_t ret = fxcrt::GetUInt16MSBFirst(pdfium::make_span(p, 2u));
-  p += 2;
+int16_t CFX_CTTGSUBTable::GetInt16(pdfium::span<const uint8_t>& p) const {
+  uint16_t ret = fxcrt::GetUInt16MSBFirst(p.first(2u));
+  p = p.subspan(2u);
   return static_cast<int16_t>(ret);
 }
 
-uint16_t CFX_CTTGSUBTable::GetUInt16(const uint8_t*& p) const {
-  // TODO(tsepez): pass actual span.
-  uint16_t ret = fxcrt::GetUInt16MSBFirst(pdfium::make_span(p, 2u));
-  p += 2;
+uint16_t CFX_CTTGSUBTable::GetUInt16(pdfium::span<const uint8_t>& p) const {
+  uint16_t ret = fxcrt::GetUInt16MSBFirst(p.first(2u));
+  p = p.subspan(2u);
   return ret;
 }
 
-int32_t CFX_CTTGSUBTable::GetInt32(const uint8_t*& p) const {
-  // TODO(tsepez): pass actual span.
-  uint32_t ret = fxcrt::GetUInt32MSBFirst(pdfium::make_span(p, 4u));
-  p += 4;
+int32_t CFX_CTTGSUBTable::GetInt32(pdfium::span<const uint8_t>& p) const {
+  uint32_t ret = fxcrt::GetUInt32MSBFirst(p.first(4u));
+  p = p.subspan(4u);
   return static_cast<int32_t>(ret);
 }
 
-uint32_t CFX_CTTGSUBTable::GetUInt32(const uint8_t*& p) const {
-  // TODO(tsepez): pass actual span.
-  uint32_t ret = fxcrt::GetUInt32MSBFirst(pdfium::make_span(p, 4u));
-  p += 4;
+uint32_t CFX_CTTGSUBTable::GetUInt32(pdfium::span<const uint8_t>& p) const {
+  uint32_t ret = fxcrt::GetUInt32MSBFirst(p.first(4u));
+  p = p.subspan(4u);
   return ret;
 }
 
@@ -200,32 +188,32 @@
 }
 
 void CFX_CTTGSUBTable::ParseScriptList(pdfium::span<const uint8_t> raw) {
-  const uint8_t* sp = raw.data();
+  pdfium::span<const uint8_t> sp = raw;
   script_list_ = std::vector<ScriptRecord>(GetUInt16(sp));
   for (auto& script : script_list_) {
     // Skip over "ScriptTag" field.
-    sp += 4;
-    script = ParseScript(&raw[GetUInt16(sp)]);
+    sp = sp.subspan(4u);
+    script = ParseScript(raw.subspan(GetUInt16(sp)));
   }
 }
 
 CFX_CTTGSUBTable::ScriptRecord CFX_CTTGSUBTable::ParseScript(
-    const uint8_t* raw) {
+    pdfium::span<const uint8_t> raw) {
   // Skip over "DefaultLangSys" field.
-  const uint8_t* sp = raw + 2;
+  pdfium::span<const uint8_t> sp = raw.subspan(2u);
   ScriptRecord result(GetUInt16(sp));
   for (auto& record : result) {
     // Skip over "LangSysTag" field.
-    sp += 4;
-    record = ParseLangSys(&raw[GetUInt16(sp)]);
+    sp = sp.subspan(4u);
+    record = ParseLangSys(raw.subspan(GetUInt16(sp)));
   }
   return result;
 }
 
 CFX_CTTGSUBTable::FeatureIndices CFX_CTTGSUBTable::ParseLangSys(
-    const uint8_t* raw) {
+    pdfium::span<const uint8_t> raw) {
   // Skip over "LookupOrder" and "ReqFeatureIndex" fields.
-  const uint8_t* sp = raw + 4;
+  pdfium::span<const uint8_t> sp = raw.subspan(4u);
   FeatureIndices result(GetUInt16(sp));
   for (auto& element : result) {
     element = GetUInt16(sp);
@@ -234,19 +222,19 @@
 }
 
 void CFX_CTTGSUBTable::ParseFeatureList(pdfium::span<const uint8_t> raw) {
-  const uint8_t* sp = raw.data();
+  pdfium::span<const uint8_t> sp = raw;
   feature_list_ = std::vector<FeatureRecord>(GetUInt16(sp));
   for (auto& record : feature_list_) {
     record.feature_tag = GetUInt32(sp);
     record.lookup_list_indices =
-        ParseFeatureLookupListIndices(&raw[GetUInt16(sp)]);
+        ParseFeatureLookupListIndices(raw.subspan(GetUInt16(sp)));
   }
 }
 
 DataVector<uint16_t> CFX_CTTGSUBTable::ParseFeatureLookupListIndices(
-    const uint8_t* raw) {
+    pdfium::span<const uint8_t> raw) {
   // Skip over "FeatureParams" field.
-  const uint8_t* sp = raw + 2;
+  pdfium::span<const uint8_t> sp = raw.subspan(2u);
   DataVector<uint16_t> result(GetUInt16(sp));
   for (auto& index : result) {
     index = GetUInt16(sp);
@@ -255,38 +243,37 @@
 }
 
 void CFX_CTTGSUBTable::ParseLookupList(pdfium::span<const uint8_t> raw) {
-  const uint8_t* sp = raw.data();
+  pdfium::span<const uint8_t> sp = raw;
   lookup_list_ = std::vector<Lookup>(GetUInt16(sp));
   for (auto& lookup : lookup_list_) {
-    lookup = ParseLookup(&raw[GetUInt16(sp)]);
+    lookup = ParseLookup(raw.subspan(GetUInt16(sp)));
   }
 }
 
-CFX_CTTGSUBTable::Lookup CFX_CTTGSUBTable::ParseLookup(const uint8_t* raw) {
-  const uint8_t* sp = raw;
+CFX_CTTGSUBTable::Lookup CFX_CTTGSUBTable::ParseLookup(
+    pdfium::span<const uint8_t> raw) {
+  pdfium::span<const uint8_t> sp = raw;
   CFX_CTTGSUBTable::Lookup result;
   result.lookup_type = GetUInt16(sp);
   // Skip over "LookupFlag" field.
-  sp += 2;
+  sp = sp.subspan(2u);
   result.sub_tables = Lookup::SubTables(GetUInt16(sp));
   if (result.lookup_type != 1) {
     return result;
   }
-
   for (auto& sub_table : result.sub_tables) {
-    sub_table = ParseSingleSubst(&raw[GetUInt16(sp)]);
+    sub_table = ParseSingleSubst(raw.subspan(GetUInt16(sp)));
   }
   return result;
 }
 
 CFX_CTTGSUBTable::CoverageFormat CFX_CTTGSUBTable::ParseCoverage(
-    const uint8_t* raw) {
-  const uint8_t* sp = raw;
+    pdfium::span<const uint8_t> raw) {
+  pdfium::span<const uint8_t> sp = raw;
   uint16_t format = GetUInt16(sp);
   if (format != 1 && format != 2) {
     return absl::monostate();
   }
-
   if (format == 1) {
     DataVector<uint16_t> glyph_array(GetUInt16(sp));
     for (auto& glyph : glyph_array) {
@@ -294,7 +281,6 @@
     }
     return glyph_array;
   }
-
   std::vector<RangeRecord> range_records(GetUInt16(sp));
   for (auto& range_rec : range_records) {
     range_rec.start = GetUInt16(sp);
@@ -305,16 +291,14 @@
 }
 
 CFX_CTTGSUBTable::SubTable CFX_CTTGSUBTable::ParseSingleSubst(
-    const uint8_t* raw) {
-  const uint8_t* sp = raw;
+    pdfium::span<const uint8_t> raw) {
+  pdfium::span<const uint8_t> sp = raw;
   uint16_t format = GetUInt16(sp);
   SubTable rec;
   if (format != 1 && format != 2) {
     return rec;
   }
-
-  uint16_t offset = GetUInt16(sp);
-  rec.coverage = ParseCoverage(&raw[offset]);
+  rec.coverage = ParseCoverage(raw.subspan(GetUInt16(sp)));
   if (format == 1) {
     rec.table_data = GetInt16(sp);
   } else {
diff --git a/core/fpdfapi/font/cfx_cttgsubtable.h b/core/fpdfapi/font/cfx_cttgsubtable.h
index 927f3a9..e5dc010 100644
--- a/core/fpdfapi/font/cfx_cttgsubtable.h
+++ b/core/fpdfapi/font/cfx_cttgsubtable.h
@@ -82,14 +82,15 @@
              pdfium::span<const uint8_t> featurelist,
              pdfium::span<const uint8_t> lookuplist);
   void ParseScriptList(pdfium::span<const uint8_t> raw);
-  ScriptRecord ParseScript(const uint8_t* raw);
-  FeatureIndices ParseLangSys(const uint8_t* raw);
+  ScriptRecord ParseScript(pdfium::span<const uint8_t> raw);
+  FeatureIndices ParseLangSys(pdfium::span<const uint8_t> raw);
   void ParseFeatureList(pdfium::span<const uint8_t> raw);
-  DataVector<uint16_t> ParseFeatureLookupListIndices(const uint8_t* raw);
+  DataVector<uint16_t> ParseFeatureLookupListIndices(
+      pdfium::span<const uint8_t> raw);
   void ParseLookupList(pdfium::span<const uint8_t> raw);
-  Lookup ParseLookup(const uint8_t* raw);
-  CoverageFormat ParseCoverage(const uint8_t* raw);
-  SubTable ParseSingleSubst(const uint8_t* raw);
+  Lookup ParseLookup(pdfium::span<const uint8_t> raw);
+  CoverageFormat ParseCoverage(pdfium::span<const uint8_t> raw);
+  SubTable ParseSingleSubst(pdfium::span<const uint8_t> raw);
 
   std::optional<uint32_t> GetVerticalGlyphSub(const FeatureRecord& feature,
                                               uint32_t glyphnum) const;
@@ -97,11 +98,11 @@
                                                uint32_t glyphnum) const;
   int GetCoverageIndex(const CoverageFormat& coverage, uint32_t g) const;
 
-  uint8_t GetUInt8(const uint8_t*& p) const;
-  int16_t GetInt16(const uint8_t*& p) const;
-  uint16_t GetUInt16(const uint8_t*& p) const;
-  int32_t GetInt32(const uint8_t*& p) const;
-  uint32_t GetUInt32(const uint8_t*& p) const;
+  uint8_t GetUInt8(pdfium::span<const uint8_t>& p) const;
+  int16_t GetInt16(pdfium::span<const uint8_t>& p) const;
+  uint16_t GetUInt16(pdfium::span<const uint8_t>& p) const;
+  int32_t GetInt32(pdfium::span<const uint8_t>& p) const;
+  uint32_t GetUInt32(pdfium::span<const uint8_t>& p) const;
 
   std::set<uint32_t> feature_set_;
   std::vector<ScriptRecord> script_list_;