Spanify FXSYS_IntToTwoHexChars() and FXSYS_IntToFourHexChars()

Pass in a fixed-size span of the required size in these functions,
instead of a pointer of unknown size. As a result, some UNSAFE_BUFFERS()
usage can go away.

While updating FXSYS_ToUTF16BE(), which this change affects, switch it
to use compile-time sizes for its span usage.

Bug: 42270715
Change-Id: I93d1a006840046afed7a1c48b0be18fafa2ad35b
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/126133
Reviewed-by: Thomas Sepez <tsepez@google.com>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.cpp b/core/fpdfapi/parser/fpdf_parser_utility.cpp
index f82bfe4..441dfd1 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_utility.cpp
@@ -132,7 +132,7 @@
       if (ch >= 0x80 || PDFCharIsWhitespace(ch) || ch == '#' ||
           PDFCharIsDelimiter(ch)) {
         dest_buf[dest_len++] = '#';
-        FXSYS_IntToTwoHexChars(ch, &dest_buf[dest_len]);
+        FXSYS_IntToTwoHexChars(ch, dest_buf.subspan(dest_len, 2u));
         dest_len += 2;
         continue;
       }
diff --git a/core/fxcrt/fx_extension.cpp b/core/fxcrt/fx_extension.cpp
index c59a46a..45393e6 100644
--- a/core/fxcrt/fx_extension.cpp
+++ b/core/fxcrt/fx_extension.cpp
@@ -8,6 +8,8 @@
 
 #include <wchar.h>
 
+#include <array>
+
 #include "core/fxcrt/check.h"
 #include "core/fxcrt/check_op.h"
 #include "core/fxcrt/compiler_specific.h"
@@ -61,23 +63,18 @@
   return dstStr;
 }
 
-// TODO(tsepez): should be UNSAFE_BUFFER_USAGE.
-void FXSYS_IntToTwoHexChars(uint8_t n, char* buf) {
-  static const char kHex[] = "0123456789ABCDEF";
-  // SAFETY: range of uint8_t keeps indices in bound.
-  UNSAFE_BUFFERS({
-    buf[0] = kHex[n / 16];
-    buf[1] = kHex[n % 16];
-  });
+void FXSYS_IntToTwoHexChars(uint8_t n, pdfium::span<char, 2u> buf) {
+  static constexpr std::array<const char, 16> kHex = {
+      '0', '1', '2', '3', '4', '5', '6', '7',
+      '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
+  };
+  buf[0] = kHex[n / 16];
+  buf[1] = kHex[n % 16];
 }
 
-// TODO(tsepez): This is UNSAFE_BUFFER_USAGE as well.
-void FXSYS_IntToFourHexChars(uint16_t n, char* buf) {
-  // SAFETY: required from caller.
-  UNSAFE_BUFFERS({
-    FXSYS_IntToTwoHexChars(n / 256, buf);
-    FXSYS_IntToTwoHexChars(n % 256, buf + 2);
-  });
+void FXSYS_IntToFourHexChars(uint16_t n, pdfium::span<char, 4u> buf) {
+  FXSYS_IntToTwoHexChars(n / 256, buf.first<2u>());
+  FXSYS_IntToTwoHexChars(n % 256, buf.subspan<2u>());
 }
 
 pdfium::span<const char> FXSYS_ToUTF16BE(uint32_t unicode,
@@ -87,12 +84,12 @@
   DCHECK(!pdfium::IsLowSurrogate(unicode));
 
   if (unicode <= 0xFFFF) {
-    FXSYS_IntToFourHexChars(unicode, buf.data());
-    return buf.first(4u);
+    FXSYS_IntToFourHexChars(unicode, buf);
+    return buf.first<4u>();
   }
   pdfium::SurrogatePair surrogate_pair(unicode);
-  FXSYS_IntToFourHexChars(surrogate_pair.high(), buf.data());
-  FXSYS_IntToFourHexChars(surrogate_pair.low(), buf.subspan(4u).data());
+  FXSYS_IntToFourHexChars(surrogate_pair.high(), buf);
+  FXSYS_IntToFourHexChars(surrogate_pair.low(), buf.subspan<4u>());
   return buf;
 }
 
diff --git a/core/fxcrt/fx_extension.h b/core/fxcrt/fx_extension.h
index 27db9fc..593b560 100644
--- a/core/fxcrt/fx_extension.h
+++ b/core/fxcrt/fx_extension.h
@@ -115,8 +115,8 @@
   return FXSYS_IsDecimalDigit(c) ? c - L'0' : 0;
 }
 
-void FXSYS_IntToTwoHexChars(uint8_t n, char* buf);
-void FXSYS_IntToFourHexChars(uint16_t n, char* buf);
+void FXSYS_IntToTwoHexChars(uint8_t n, pdfium::span<char, 2u> buf);
+void FXSYS_IntToFourHexChars(uint16_t n, pdfium::span<char, 4u> buf);
 
 // Converts `unicode` to a UTF16-BE hex string. Writes the string into `buf` and
 // returns the portion of `buf` used to store the string. The returned span is
diff --git a/core/fxcrt/fx_extension_unittest.cpp b/core/fxcrt/fx_extension_unittest.cpp
index b040549..15e0879 100644
--- a/core/fxcrt/fx_extension_unittest.cpp
+++ b/core/fxcrt/fx_extension_unittest.cpp
@@ -84,33 +84,33 @@
 }
 
 TEST(fxcrt, FXSYSIntToTwoHexChars) {
-  char buf[3] = {0};
+  char buf[2] = {0};
   FXSYS_IntToTwoHexChars(0x0, buf);
-  EXPECT_STREQ("00", buf);
+  EXPECT_THAT(buf, ElementsAre('0', '0'));
   FXSYS_IntToTwoHexChars(0x9, buf);
-  EXPECT_STREQ("09", buf);
+  EXPECT_THAT(buf, ElementsAre('0', '9'));
   FXSYS_IntToTwoHexChars(0xA, buf);
-  EXPECT_STREQ("0A", buf);
+  EXPECT_THAT(buf, ElementsAre('0', 'A'));
   FXSYS_IntToTwoHexChars(0x8C, buf);
-  EXPECT_STREQ("8C", buf);
+  EXPECT_THAT(buf, ElementsAre('8', 'C'));
   FXSYS_IntToTwoHexChars(0xBE, buf);
-  EXPECT_STREQ("BE", buf);
+  EXPECT_THAT(buf, ElementsAre('B', 'E'));
   FXSYS_IntToTwoHexChars(0xD0, buf);
-  EXPECT_STREQ("D0", buf);
+  EXPECT_THAT(buf, ElementsAre('D', '0'));
   FXSYS_IntToTwoHexChars(0xFF, buf);
-  EXPECT_STREQ("FF", buf);
+  EXPECT_THAT(buf, ElementsAre('F', 'F'));
 }
 
 TEST(fxcrt, FXSYSIntToFourHexChars) {
-  char buf[5] = {0};
+  char buf[4] = {0};
   FXSYS_IntToFourHexChars(0x0, buf);
-  EXPECT_STREQ("0000", buf);
+  EXPECT_THAT(buf, ElementsAre('0', '0', '0', '0'));
   FXSYS_IntToFourHexChars(0xA23, buf);
-  EXPECT_STREQ("0A23", buf);
+  EXPECT_THAT(buf, ElementsAre('0', 'A', '2', '3'));
   FXSYS_IntToFourHexChars(0xB701, buf);
-  EXPECT_STREQ("B701", buf);
+  EXPECT_THAT(buf, ElementsAre('B', '7', '0', '1'));
   FXSYS_IntToFourHexChars(0xFFFF, buf);
-  EXPECT_STREQ("FFFF", buf);
+  EXPECT_THAT(buf, ElementsAre('F', 'F', 'F', 'F'));
 }
 
 TEST(fxcrt, FXSYSToUTF16BE) {
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp
index 59c65c3..a4efc18 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -523,13 +523,13 @@
   ByteString bsGUID;
   {
     // Span's lifetime must end before ReleaseBuffer() below.
-    pdfium::span<char> pBuf = bsGUID.GetBuffer(40);
+    pdfium::span<char> guid_span = bsGUID.GetBuffer(40);
     size_t out_index = 0;
     for (size_t i = 0; i < 16; ++i, out_index += 2) {
       if (bSeparator && (i == 4 || i == 6 || i == 8 || i == 10)) {
-        pBuf[out_index++] = L'-';
+        guid_span[out_index++] = L'-';
       }
-      FXSYS_IntToTwoHexChars(data[i], &pBuf[out_index]);
+      FXSYS_IntToTwoHexChars(data[i], guid_span.subspan(out_index, 2u));
     }
   }
   bsGUID.ReleaseBuffer(bSeparator ? 36 : 32);