Re-work string template constructors

Allow better implicit conversions from spans.

-- avoid some confusion when using results of binary buffers
   between const spans (which are ok) and non-const (not ok) by
   forcing all existing callers into the const form of GetSpan().
-- add GetMutableSpan() for a few places where needed.
-- preserve property that strings created from empty vectors get
   empty data pointers (makes null-checks faster by a tad) and
   passes existing tests.

Change-Id: I3557224c6ad0251c26217febd8d28af74efedea8
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/98072
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_crypto_handler.cpp b/core/fpdfapi/parser/cpdf_crypto_handler.cpp
index bb49ab9..7965769 100644
--- a/core/fpdfapi/parser/cpdf_crypto_handler.cpp
+++ b/core/fpdfapi/parser/cpdf_crypto_handler.cpp
@@ -147,8 +147,9 @@
   if (m_Cipher == Cipher::kRC4) {
     size_t old_size = dest_buf.GetSize();
     dest_buf.AppendBlock(source.data(), source.size());
-    CRYPT_ArcFourCrypt(static_cast<CRYPT_rc4_context*>(context),
-                       dest_buf.GetSpan().subspan(old_size, source.size()));
+    CRYPT_ArcFourCrypt(
+        static_cast<CRYPT_rc4_context*>(context),
+        dest_buf.GetMutableSpan().subspan(old_size, source.size()));
     return true;
   }
   AESCryptContext* pContext = static_cast<AESCryptContext*>(context);
diff --git a/core/fxcrt/binary_buffer.cpp b/core/fxcrt/binary_buffer.cpp
index d714d2d..e527e26 100644
--- a/core/fxcrt/binary_buffer.cpp
+++ b/core/fxcrt/binary_buffer.cpp
@@ -47,7 +47,7 @@
   m_DataSize -= count;
 }
 
-pdfium::span<uint8_t> BinaryBuffer::GetSpan() {
+pdfium::span<uint8_t> BinaryBuffer::GetMutableSpan() {
   return {m_buffer.data(), GetSize()};
 }
 
diff --git a/core/fxcrt/binary_buffer.h b/core/fxcrt/binary_buffer.h
index 478df0d..e23812b 100644
--- a/core/fxcrt/binary_buffer.h
+++ b/core/fxcrt/binary_buffer.h
@@ -28,7 +28,7 @@
 
   BinaryBuffer& operator=(const BinaryBuffer& that) = delete;
 
-  pdfium::span<uint8_t> GetSpan();
+  pdfium::span<uint8_t> GetMutableSpan();
   pdfium::span<const uint8_t> GetSpan() const;
   bool IsEmpty() const { return GetLength() == 0; }
   size_t GetSize() const { return m_DataSize; }  // In bytes.
diff --git a/core/fxcrt/string_view_template.h b/core/fxcrt/string_view_template.h
index d2f0d41..28af5b1 100644
--- a/core/fxcrt/string_view_template.h
+++ b/core/fxcrt/string_view_template.h
@@ -12,7 +12,6 @@
 #include <algorithm>
 #include <iterator>
 #include <type_traits>
-#include <vector>
 
 #include "core/fxcrt/fx_system.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -49,28 +48,26 @@
       : m_Span(reinterpret_cast<const UnsignedType*>(ptr),
                ptr ? FXSYS_len(ptr) : 0) {}
 
-  constexpr StringViewTemplate(const CharType* ptr, size_t len) noexcept
-      : m_Span(reinterpret_cast<const UnsignedType*>(ptr), len) {}
+  constexpr StringViewTemplate(const CharType* ptr, size_t size) noexcept
+      : m_Span(reinterpret_cast<const UnsignedType*>(ptr), size) {}
+
+  template <typename E = typename std::enable_if<
+                !std::is_same<UnsignedType, CharType>::value>::type>
+  constexpr StringViewTemplate(const UnsignedType* ptr, size_t size) noexcept
+      : m_Span(ptr, size) {}
 
   explicit constexpr StringViewTemplate(
       const pdfium::span<const CharType>& other) noexcept
-      : m_Span(reinterpret_cast<const UnsignedType*>(other.data()),
+      : m_Span(other.size()
+                   ? reinterpret_cast<const UnsignedType*>(other.data())
+                   : nullptr,
                other.size()) {}
 
-  template <typename U = UnsignedType>
+  template <typename E = typename std::enable_if<
+                !std::is_same<UnsignedType, CharType>::value>::type>
   constexpr StringViewTemplate(
-      const UnsignedType* ptr,
-      size_t size,
-      typename std::enable_if<!std::is_same<U, CharType>::value>::type* =
-          0) noexcept
-      : m_Span(ptr, size) {}
-
-  template <typename U = UnsignedType>
-  StringViewTemplate(
-      const pdfium::span<U> other,
-      typename std::enable_if<!std::is_same<U, CharType>::value>::type* =
-          0) noexcept
-      : m_Span(other) {}
+      const pdfium::span<const UnsignedType>& other) noexcept
+      : m_Span(other.size() ? other.data() : nullptr, other.size()) {}
 
   // Deliberately implicit to avoid calling on every char literal.
   // |ch| must be an lvalue that outlives the StringViewTemplate.
@@ -78,12 +75,6 @@
   constexpr StringViewTemplate(const CharType& ch) noexcept
       : m_Span(reinterpret_cast<const UnsignedType*>(&ch), 1) {}
 
-  // Any changes to |vec| invalidate the string.
-  template <typename AllocType>
-  explicit StringViewTemplate(
-      const std::vector<UnsignedType, AllocType>& vec) noexcept
-      : m_Span(!vec.empty() ? vec.data() : nullptr, vec.size()) {}
-
   StringViewTemplate& operator=(const CharType* src) {
     m_Span = pdfium::span<const UnsignedType>(
         reinterpret_cast<const UnsignedType*>(src), src ? FXSYS_len(src) : 0);
diff --git a/fxjs/cfx_globaldata.cpp b/fxjs/cfx_globaldata.cpp
index 1898703..1b8ecd8 100644
--- a/fxjs/cfx_globaldata.cpp
+++ b/fxjs/cfx_globaldata.cpp
@@ -389,7 +389,7 @@
   sFile.AppendBlock(&dwSize, sizeof(uint32_t));
   sFile.AppendSpan(sData.GetSpan());
 
-  CRYPT_ArcFourCryptBlock(sFile.GetSpan(), kRC4KEY);
+  CRYPT_ArcFourCryptBlock(sFile.GetMutableSpan(), kRC4KEY);
   return m_pDelegate->StoreBuffer(sFile.GetSpan());
 }