Templatize SpanFromFPDFApiArgs()

Allow SpanFromFPDFApiArgs() to take `buflen` of any integral type. The
value gets converted to size_t via checked_cast() for use in the span
constructor. Currently, SpanFromFPDFApiArgs() passes in a `buflen` of
type unsigned long.

Change-Id: Id187312b2ef02c1f5cbb90c01d39514863d77623
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/121971
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Tom Sepez <tsepez@google.com>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_helpers.cpp b/fpdfsdk/cpdfsdk_helpers.cpp
index cab740e..04f7c8c 100644
--- a/fpdfsdk/cpdfsdk_helpers.cpp
+++ b/fpdfsdk/cpdfsdk_helpers.cpp
@@ -237,15 +237,6 @@
                         FPDFWideStringLength(wide_string) * 2)));
 }
 
-pdfium::span<char> SpanFromFPDFApiArgs(void* buffer, unsigned long buflen) {
-  if (!buffer) {
-    // API convention is to ignore `buflen` arg when `buffer` is NULL.
-    return pdfium::span<char>();
-  }
-  // SAFETY: required from caller, enforced by UNSAFE_BUFFER_USAGE in header.
-  return UNSAFE_BUFFERS(pdfium::make_span(static_cast<char*>(buffer), buflen));
-}
-
 #ifdef PDF_ENABLE_XFA
 RetainPtr<IFX_SeekableStream> MakeSeekableStream(
     FPDF_FILEHANDLER* pFilehandler) {
diff --git a/fpdfsdk/cpdfsdk_helpers.h b/fpdfsdk/cpdfsdk_helpers.h
index 51478b4..5bdb685 100644
--- a/fpdfsdk/cpdfsdk_helpers.h
+++ b/fpdfsdk/cpdfsdk_helpers.h
@@ -13,6 +13,7 @@
 #include "core/fpdfapi/page/cpdf_page.h"
 #include "core/fpdfapi/parser/cpdf_parser.h"
 #include "core/fxcrt/compiler_specific.h"
+#include "core/fxcrt/numerics/safe_conversions.h"
 #include "core/fxcrt/retain_ptr.h"
 #include "core/fxcrt/span.h"
 #include "core/fxge/cfx_path.h"
@@ -255,9 +256,22 @@
 UNSAFE_BUFFER_USAGE WideString
 WideStringFromFPDFWideString(FPDF_WIDESTRING wide_string);
 
-UNSAFE_BUFFER_USAGE pdfium::span<char> SpanFromFPDFApiArgs(
-    void* buffer,
-    unsigned long buflen);
+// Public APIs are not consistent w.r.t. the type used to represent buffer
+// length, while internal code generally expects size_t. To get consistent
+// behavior regardless of size type, templatize SpanFromFPDFApiArgs().
+//
+// TODO(crbug.com/42270941): Switch to concepts.
+template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
+UNSAFE_BUFFER_USAGE pdfium::span<char> SpanFromFPDFApiArgs(void* buffer,
+                                                           T buflen) {
+  if (!buffer) {
+    // API convention is to ignore `buflen` arg when `buffer` is NULL.
+    return pdfium::span<char>();
+  }
+  // SAFETY: required from caller, enforced by UNSAFE_BUFFER_USAGE in header.
+  return UNSAFE_BUFFERS(pdfium::make_span(
+      static_cast<char*>(buffer), pdfium::checked_cast<size_t>(buflen)));
+}
 
 #ifdef PDF_ENABLE_XFA
 // Layering prevents fxcrt from knowing about FPDF_FILEHANDLER, so this can't
diff --git a/fpdfsdk/fpdf_edittext.cpp b/fpdfsdk/fpdf_edittext.cpp
index 9126c61..56ea16a 100644
--- a/fpdfsdk/fpdf_edittext.cpp
+++ b/fpdfsdk/fpdf_edittext.cpp
@@ -873,8 +873,7 @@
     return false;
 
   // SAFETY: required from caller.
-  auto result_span = UNSAFE_BUFFERS(
-      SpanFromFPDFApiArgs(buffer, pdfium::checked_cast<unsigned long>(buflen)));
+  auto result_span = UNSAFE_BUFFERS(SpanFromFPDFApiArgs(buffer, buflen));
   pdfium::span<const uint8_t> data = cfont->GetFont()->GetFontSpan();
   fxcrt::try_spancpy(result_span, data);
   *out_buflen = data.size();