Import base::span_from_ref() into span.h

PDFium equivalent of chromium change at https://crrev.com/1248905

Use it to remove some two-argument forms of make_span(). These are
considered dangerous in general because the length can be specified
incorrectly.

Change-Id: Ifd983034731aa0b7cf993a176bca7f1c4eca587a
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/115671
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_cidfont.cpp b/core/fpdfapi/font/cpdf_cidfont.cpp
index b6cf44d..c47cb0f 100644
--- a/core/fpdfapi/font/cpdf_cidfont.cpp
+++ b/core/fpdfapi/font/cpdf_cidfont.cpp
@@ -342,7 +342,7 @@
   size_t ret = FX_MultiByteToWideChar(
       kCharsetCodePages[static_cast<size_t>(m_pCMap->GetCoding())],
       ByteStringView(reinterpret_cast<const char*>(&charcode), charsize),
-      pdfium::make_span(&unicode, 1u));
+      pdfium::span_from_ref(unicode));
   return ret == 1 ? unicode : 0;
 #else
   if (!m_pCMap->GetEmbedMap())
diff --git a/core/fpdfapi/page/cpdf_stitchfunc.cpp b/core/fpdfapi/page/cpdf_stitchfunc.cpp
index 21d7340..2a303bf 100644
--- a/core/fpdfapi/page/cpdf_stitchfunc.cpp
+++ b/core/fpdfapi/page/cpdf_stitchfunc.cpp
@@ -117,6 +117,6 @@
   input = Interpolate(input, m_bounds[i], m_bounds[i + 1], m_encode[i * 2],
                       m_encode[i * 2 + 1]);
   return m_pSubFunctions[i]
-      ->Call(pdfium::make_span(&input, 1u), results)
+      ->Call(pdfium::span_from_ref(input), results)
       .has_value();
 }
diff --git a/core/fpdfapi/parser/cpdf_security_handler.cpp b/core/fpdfapi/parser/cpdf_security_handler.cpp
index b0a1729..96da9c4 100644
--- a/core/fpdfapi/parser/cpdf_security_handler.cpp
+++ b/core/fpdfapi/parser/cpdf_security_handler.cpp
@@ -55,14 +55,14 @@
   ByteString okey = pEncrypt->GetByteStringFor("O");
   CRYPT_MD5Update(&md5, okey.raw_span());
   uint32_t perm = pEncrypt->GetIntegerFor("P");
-  CRYPT_MD5Update(&md5, pdfium::as_bytes(pdfium::make_span(&perm, 1u)));
+  CRYPT_MD5Update(&md5, pdfium::as_bytes(pdfium::span_from_ref(perm)));
   if (!file_id.IsEmpty())
     CRYPT_MD5Update(&md5, file_id.raw_span());
   const bool is_revision_3_or_greater = pEncrypt->GetIntegerFor("R") >= 3;
   if (!ignore_metadata && is_revision_3_or_greater &&
       !pEncrypt->GetBooleanFor("EncryptMetadata", true)) {
     constexpr uint32_t tag = 0xFFFFFFFF;
-    CRYPT_MD5Update(&md5, pdfium::as_bytes(pdfium::make_span(&tag, 1u)));
+    CRYPT_MD5Update(&md5, pdfium::as_bytes(pdfium::span_from_ref(tag)));
   }
   uint8_t digest[16];
   CRYPT_MD5Finish(&md5, digest);
diff --git a/core/fpdfapi/render/cpdf_docrenderdata.cpp b/core/fpdfapi/render/cpdf_docrenderdata.cpp
index 02f71fc..aeea585 100644
--- a/core/fpdfapi/render/cpdf_docrenderdata.cpp
+++ b/core/fpdfapi/render/cpdf_docrenderdata.cpp
@@ -114,7 +114,7 @@
           samples[i][v] = v;
           continue;
         }
-        pFuncs[i]->Call(pdfium::make_span(&input, 1u), output);
+        pFuncs[i]->Call(pdfium::span_from_ref(input), output);
         size_t o = FXSYS_roundf(output[0] * 255);
         if (o != v)
           bIdentity = false;
@@ -125,7 +125,7 @@
     for (size_t v = 0; v < CPDF_TransferFunc::kChannelSampleSize; ++v) {
       float input = static_cast<float>(v) / 255.0f;
       if (pFuncs[0]->CountOutputs() <= kMaxOutputs)
-        pFuncs[0]->Call(pdfium::make_span(&input, 1u), output);
+        pFuncs[0]->Call(pdfium::span_from_ref(input), output);
       size_t o = FXSYS_roundf(output[0] * 255);
       if (o != v)
         bIdentity = false;
diff --git a/core/fpdfapi/render/cpdf_rendershading.cpp b/core/fpdfapi/render/cpdf_rendershading.cpp
index 470a3db..3c01d55 100644
--- a/core/fpdfapi/render/cpdf_rendershading.cpp
+++ b/core/fpdfapi/render/cpdf_rendershading.cpp
@@ -77,7 +77,7 @@
       if (!func)
         continue;
       absl::optional<uint32_t> nresults =
-          func->Call(pdfium::make_span(&input, 1u), result_span);
+          func->Call(pdfium::span_from_ref(input), result_span);
       if (nresults.has_value())
         result_span = result_span.subspan(nresults.value());
     }
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index 652afe0..885cf8a 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -1385,7 +1385,7 @@
     std::vector<float> results(pFunc->CountOutputs());
     for (size_t i = 0; i < transfers.size(); ++i) {
       float input = i / 255.0f;
-      pFunc->Call(pdfium::make_span(&input, 1u), results);
+      pFunc->Call(pdfium::span_from_ref(input), results);
       transfers[i] = FXSYS_roundf(results[0] * 255);
     }
   } else {
diff --git a/core/fxcodec/bmp/cfx_bmpdecompressor.cpp b/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
index 7e63423..40a8163 100644
--- a/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
+++ b/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
@@ -90,7 +90,7 @@
 BmpDecoder::Status CFX_BmpDecompressor::ReadBmpHeader() {
   BmpFileHeader bmp_header;
   if (!ReadAllOrNone(
-          pdfium::as_writable_bytes(pdfium::make_span(&bmp_header, 1u)))) {
+          pdfium::as_writable_bytes(pdfium::span_from_ref(bmp_header)))) {
     return BmpDecoder::Status::kContinue;
   }
 
@@ -105,7 +105,7 @@
 
   size_t pos = input_buffer_->GetPosition();
   if (!ReadAllOrNone(
-          pdfium::as_writable_bytes(pdfium::make_span(&img_ifh_size_, 1u)))) {
+          pdfium::as_writable_bytes(pdfium::span_from_ref(img_ifh_size_)))) {
     return BmpDecoder::Status::kContinue;
   }
   if (!input_buffer_->Seek(pos))
@@ -126,7 +126,7 @@
     pal_type_ = PalType::kOld;
     BmpCoreHeader bmp_core_header;
     if (!ReadAllOrNone(pdfium::as_writable_bytes(
-            pdfium::make_span(&bmp_core_header, 1u)))) {
+            pdfium::span_from_ref(bmp_core_header)))) {
       return BmpDecoder::Status::kContinue;
     }
 
@@ -144,7 +144,7 @@
   if (img_ifh_size_ == kBmpInfoHeaderSize) {
     BmpInfoHeader bmp_info_header;
     if (!ReadAllOrNone(pdfium::as_writable_bytes(
-            pdfium::make_span(&bmp_info_header, 1u)))) {
+            pdfium::span_from_ref(bmp_info_header)))) {
       return BmpDecoder::Status::kContinue;
     }
 
@@ -173,7 +173,7 @@
   FX_SAFE_SIZE_T new_pos = input_buffer_->GetPosition();
   BmpInfoHeader bmp_info_header;
   if (!ReadAllOrNone(
-          pdfium::as_writable_bytes(pdfium::make_span(&bmp_info_header, 1u)))) {
+          pdfium::as_writable_bytes(pdfium::span_from_ref(bmp_info_header)))) {
     return BmpDecoder::Status::kContinue;
   }
 
@@ -461,13 +461,13 @@
   uint8_t first_part;
   col_num_ = 0;
   while (true) {
-    if (!ReadAllOrNone(pdfium::make_span(&first_part, 1u))) {
+    if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
       return BmpDecoder::Status::kContinue;
     }
 
     switch (first_part) {
       case kRleMarker: {
-        if (!ReadAllOrNone(pdfium::make_span(&first_part, 1u))) {
+        if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
           return BmpDecoder::Status::kContinue;
         }
 
@@ -537,7 +537,7 @@
           return BmpDecoder::Status::kFail;
 
         uint8_t second_part;
-        if (!ReadAllOrNone(pdfium::make_span(&second_part, 1u))) {
+        if (!ReadAllOrNone(pdfium::span_from_ref(second_part))) {
           return BmpDecoder::Status::kContinue;
         }
 
@@ -557,13 +557,13 @@
   uint8_t first_part;
   col_num_ = 0;
   while (true) {
-    if (!ReadAllOrNone(pdfium::make_span(&first_part, 1u))) {
+    if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
       return BmpDecoder::Status::kContinue;
     }
 
     switch (first_part) {
       case kRleMarker: {
-        if (!ReadAllOrNone(pdfium::make_span(&first_part, 1u))) {
+        if (!ReadAllOrNone(pdfium::span_from_ref(first_part))) {
           return BmpDecoder::Status::kContinue;
         }
 
@@ -646,7 +646,7 @@
           first_part = avail_size - 1;
         }
         uint8_t second_part;
-        if (!ReadAllOrNone(pdfium::make_span(&second_part, 1u))) {
+        if (!ReadAllOrNone(pdfium::span_from_ref(second_part))) {
           return BmpDecoder::Status::kContinue;
         }
 
diff --git a/core/fxcodec/gif/cfx_gifcontext_unittest.cpp b/core/fxcodec/gif/cfx_gifcontext_unittest.cpp
index 75b3ec1..bcf8ea9 100644
--- a/core/fxcodec/gif/cfx_gifcontext_unittest.cpp
+++ b/core/fxcodec/gif/cfx_gifcontext_unittest.cpp
@@ -205,9 +205,7 @@
       uint8_t palette[4 * sizeof(CFX_GifPalette)];
     } data = {{0x0A, 0x00, 0x00, 0x0F, 0xA9, 0x01, 0x02},
               {0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1}};
-    context.SetTestInputBuffer(
-        {reinterpret_cast<uint8_t*>(&data), sizeof(data)});
-
+    context.SetTestInputBuffer(pdfium::as_bytes(pdfium::span_from_ref(data)));
     EXPECT_EQ(GifDecoder::Status::kSuccess,
               context.ReadLogicalScreenDescriptor());
 
@@ -233,9 +231,7 @@
       uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
     } data = {{'N', 'O', 'T', 'G', 'I', 'F'},
               {0x0A, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x02}};
-    context.SetTestInputBuffer(
-        {reinterpret_cast<uint8_t*>(&data), sizeof(data)});
-
+    context.SetTestInputBuffer(pdfium::as_bytes(pdfium::span_from_ref(data)));
     EXPECT_EQ(GifDecoder::Status::kError, context.ReadHeader());
     EXPECT_EQ(sizeof(data.signature), context.InputBuffer()->GetPosition());
     context.SetTestInputBuffer({});
@@ -243,9 +239,7 @@
   // Short after signature
   {
     uint8_t signature[] = {'G', 'I', 'F', '8', '7', 'a'};
-    context.SetTestInputBuffer(
-        {reinterpret_cast<uint8_t*>(&signature), sizeof(signature)});
-
+    context.SetTestInputBuffer(signature);
     EXPECT_EQ(GifDecoder::Status::kUnfinished, context.ReadHeader());
     EXPECT_EQ(sizeof(signature), context.InputBuffer()->GetPosition());
     context.SetTestInputBuffer({});
@@ -257,9 +251,7 @@
       uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
     } data = {{'G', 'I', 'F', '8', '7', 'a'},
               {0x0A, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x02}};
-    context.SetTestInputBuffer(
-        {reinterpret_cast<uint8_t*>(&data), sizeof(data)});
-
+    context.SetTestInputBuffer(pdfium::as_bytes(pdfium::span_from_ref(data)));
     EXPECT_EQ(GifDecoder::Status::kSuccess, context.ReadHeader());
     EXPECT_EQ(sizeof(data), context.InputBuffer()->GetPosition());
     EXPECT_EQ(0x000A, context.width_);
@@ -274,9 +266,7 @@
       uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
     } data = {{'G', 'I', 'F', '8', '7', 'a'},
               {0x0A, 0x00, 0x00, 0x0F, 0x80, 0x01, 0x02}};
-    context.SetTestInputBuffer(
-        {reinterpret_cast<uint8_t*>(&data), sizeof(data)});
-
+    context.SetTestInputBuffer(pdfium::as_bytes(pdfium::span_from_ref(data)));
     EXPECT_EQ(GifDecoder::Status::kUnfinished, context.ReadHeader());
     EXPECT_EQ(sizeof(data.signature), context.InputBuffer()->GetPosition());
     context.SetTestInputBuffer({});
@@ -290,9 +280,7 @@
     } data = {{'G', 'I', 'F', '8', '7', 'a'},
               {0x0A, 0x00, 0x00, 0x0F, 0xA9, 0x01, 0x02},
               {0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1}};
-    context.SetTestInputBuffer(
-        {reinterpret_cast<uint8_t*>(&data), sizeof(data)});
-
+    context.SetTestInputBuffer(pdfium::as_bytes(pdfium::span_from_ref(data)));
     EXPECT_EQ(GifDecoder::Status::kSuccess, context.ReadHeader());
     EXPECT_EQ(sizeof(data), context.InputBuffer()->GetPosition());
     EXPECT_EQ(0x000A, context.width_);
diff --git a/core/fxcrt/binary_buffer.cpp b/core/fxcrt/binary_buffer.cpp
index 8d3335e..1fa8bc7 100644
--- a/core/fxcrt/binary_buffer.cpp
+++ b/core/fxcrt/binary_buffer.cpp
@@ -104,19 +104,19 @@
 }
 
 void BinaryBuffer::AppendUint8(uint8_t value) {
-  AppendSpan({&value, 1u});
+  AppendSpan(pdfium::span_from_ref(value));
 }
 
 void BinaryBuffer::AppendUint16(uint16_t value) {
-  AppendSpan({reinterpret_cast<uint8_t*>(&value), sizeof(value)});
+  AppendSpan(pdfium::as_bytes(pdfium::span_from_ref(value)));
 }
 
 void BinaryBuffer::AppendUint32(uint32_t value) {
-  AppendSpan({reinterpret_cast<uint8_t*>(&value), sizeof(value)});
+  AppendSpan(pdfium::as_bytes(pdfium::span_from_ref(value)));
 }
 
 void BinaryBuffer::AppendDouble(double value) {
-  AppendSpan({reinterpret_cast<uint8_t*>(&value), sizeof(value)});
+  AppendSpan(pdfium::as_bytes(pdfium::span_from_ref(value)));
 }
 
 }  // namespace fxcrt
diff --git a/core/fxge/win32/cwin32_platform.cpp b/core/fxge/win32/cwin32_platform.cpp
index 461a915..50d1d75 100644
--- a/core/fxge/win32/cwin32_platform.cpp
+++ b/core/fxge/win32/cwin32_platform.cpp
@@ -159,7 +159,7 @@
   size_t font_size = GetFontData(hFont, 0, {});
   if (font_size != GDI_ERROR && font_size >= sizeof(uint32_t)) {
     uint32_t header;
-    auto span = pdfium::as_writable_bytes(pdfium::make_span(&header, 1u));
+    auto span = pdfium::as_writable_bytes(pdfium::span_from_ref(header));
     GetFontData(hFont, 0, span);
     header = FXSYS_UINT32_GET_MSBFIRST(span);
     ret = header == FXBSTR_ID('O', 'T', 'T', 'O') ||
diff --git a/fpdfsdk/fpdf_edittext.cpp b/fpdfsdk/fpdf_edittext.cpp
index 54bf4a4..ee8212a 100644
--- a/fpdfsdk/fpdf_edittext.cpp
+++ b/fpdfsdk/fpdf_edittext.cpp
@@ -836,7 +836,7 @@
 
   uint32_t charcode = pFont->CharCodeFromUnicode(static_cast<wchar_t>(glyph));
   std::vector<TextCharPos> pos =
-      GetCharPosList(pdfium::make_span(&charcode, 1u),
+      GetCharPosList(pdfium::span_from_ref(charcode),
                      pdfium::span<const float>(), pFont, font_size);
   if (pos.empty())
     return nullptr;
diff --git a/third_party/base/containers/span.h b/third_party/base/containers/span.h
index 68be934..bfead3d 100644
--- a/third_party/base/containers/span.h
+++ b/third_party/base/containers/span.h
@@ -180,6 +180,7 @@
 //
 // Additions beyond the C++ standard draft
 // - as_byte_span() function.
+// - span_from_ref() function.
 
 // [span], class template span
 template <typename T>
@@ -356,6 +357,14 @@
   return span<T>(container);
 }
 
+// `span_from_ref` converts a reference to T into a span of length 1.  This is a
+// non-std helper that is inspired by the `std::slice::from_ref()` function from
+// Rust.
+template <typename T>
+static constexpr span<T> span_from_ref(T& single_object) noexcept {
+  return span<T>(&single_object, 1u);
+}
+
 // Convenience function for converting an object which is itself convertible
 // to span into a span of bytes (i.e. span of const uint8_t). Typically used
 // to convert std::string or string-objects holding chars, or std::vector