Begin marking unsafe libc functions as UNSAFE_BUFFERS().

Prepare for a time when the plugin will start enforcing these.
This is not an exhaustive list, but covers many of the most common
cases.

Change-Id: I36fdf195e7716e9f8ccfeda5164b5ba71ec70cd0
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/127271
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fdrm/fx_crypt_unittest.cpp b/core/fdrm/fx_crypt_unittest.cpp
index 91fe60e..8b856ff 100644
--- a/core/fdrm/fx_crypt_unittest.cpp
+++ b/core/fdrm/fx_crypt_unittest.cpp
@@ -524,7 +524,7 @@
   static const char kInput[] =
       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
-  EXPECT_EQ(112u, strlen(kInput));
+  EXPECT_EQ(112u, UNSAFE_TODO(strlen(kInput)));
   DataVector<uint8_t> actual =
       CRYPT_SHA384Generate(ByteStringView(kInput).unsigned_span());
   EXPECT_THAT(
@@ -573,7 +573,7 @@
   static const char kInput[] =
       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
-  EXPECT_EQ(112u, strlen(kInput));
+  EXPECT_EQ(112u, UNSAFE_TODO(strlen(kInput)));
   DataVector<uint8_t> actual =
       CRYPT_SHA512Generate(ByteStringView(kInput).unsigned_span());
   EXPECT_THAT(
diff --git a/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp b/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp
index da69d50..87d0154 100644
--- a/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp
+++ b/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp
@@ -57,7 +57,7 @@
   size_t trailer_start = saved_data.find(kTrailerBeforeSecondID);
   static constexpr size_t kIdLen = 32;
   size_t trailer_continuation =
-      trailer_start + strlen(kTrailerBeforeSecondID) + kIdLen;
+      trailer_start + UNSAFE_TODO(strlen(kTrailerBeforeSecondID)) + kIdLen;
   std::string data_after_second_id = saved_data.substr(trailer_continuation);
   EXPECT_THAT(data_after_second_id, testing::StartsWith(">]>>\r\n"));
 }
diff --git a/core/fpdfapi/font/cpdf_truetypefont.cpp b/core/fpdfapi/font/cpdf_truetypefont.cpp
index 8703bc8..e3be907 100644
--- a/core/fpdfapi/font/cpdf_truetypefont.cpp
+++ b/core/fpdfapi/font/cpdf_truetypefont.cpp
@@ -101,7 +101,7 @@
           !name) {
         continue;
       }
-      if (strcmp(name, ".notdef") == 0) {
+      if (UNSAFE_TODO(strcmp(name, ".notdef")) == 0) {
         m_GlyphIndex[charcode] = face->GetCharIndex(32);
         continue;
       }
diff --git a/core/fpdfapi/font/cpdf_type1font.cpp b/core/fpdfapi/font/cpdf_type1font.cpp
index 126a9e0..895ee61 100644
--- a/core/fpdfapi/font/cpdf_type1font.cpp
+++ b/core/fpdfapi/font/cpdf_type1font.cpp
@@ -13,6 +13,7 @@
 
 #include "build/build_config.h"
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
+#include "core/fxcrt/compiler_specific.h"
 #include "core/fxcrt/fx_memcpy_wrappers.h"
 #include "core/fxcrt/fx_system.h"
 #include "core/fxcrt/span_util.h"
@@ -189,7 +190,8 @@
 #if BUILDFLAG(IS_APPLE)
       CalcExtGID(charcode);
 #endif
-      if (m_GlyphIndex[charcode] == 0 && strcmp(name, ".notdef") == 0) {
+      if (m_GlyphIndex[charcode] == 0 &&
+          UNSAFE_TODO(strcmp(name, ".notdef")) == 0) {
         m_Encoding.SetUnicode(charcode, 0x20);
         m_GlyphIndex[charcode] = face->GetCharIndex(0x20);
 #if BUILDFLAG(IS_APPLE)
@@ -298,7 +300,8 @@
     if (m_GlyphIndex[charcode] != 0)
       continue;
 
-    if (strcmp(name, ".notdef") != 0 && strcmp(name, "space") != 0) {
+    if (UNSAFE_TODO(strcmp(name, ".notdef")) != 0 &&
+        UNSAFE_TODO(strcmp(name, "space")) != 0) {
       m_GlyphIndex[charcode] =
           face->GetCharIndex(bUnicode ? m_Encoding.UnicodeFromCharCode(charcode)
                                       : static_cast<uint32_t>(charcode));
diff --git a/core/fpdfapi/page/cpdf_iccprofile.cpp b/core/fpdfapi/page/cpdf_iccprofile.cpp
index c469edd..1d813f6 100644
--- a/core/fpdfapi/page/cpdf_iccprofile.cpp
+++ b/core/fpdfapi/page/cpdf_iccprofile.cpp
@@ -10,12 +10,15 @@
 
 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
 #include "core/fxcodec/icc/icc_transform.h"
+#include "core/fxcrt/compiler_specific.h"
 
 namespace {
 
 bool DetectSRGB(pdfium::span<const uint8_t> span) {
   static const char kSRGB[] = "sRGB IEC61966-2.1";
-  return span.size() == 3144 && memcmp(&span[400], kSRGB, strlen(kSRGB)) == 0;
+  // SAFETY: size checked on LHS of &&-expression.
+  return span.size() == 3144 &&
+         UNSAFE_BUFFERS(memcmp(&span[400], kSRGB, strlen(kSRGB))) == 0;
 }
 
 }  // namespace
diff --git a/core/fpdfapi/parser/cpdf_object_unittest.cpp b/core/fpdfapi/parser/cpdf_object_unittest.cpp
index 5cd3b46..520e977 100644
--- a/core/fpdfapi/parser/cpdf_object_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_unittest.cpp
@@ -176,7 +176,8 @@
         if (span1.size() != span2.size())
           return false;
 
-        return memcmp(span1.data(), span2.data(), span2.size()) == 0;
+        return UNSAFE_TODO(memcmp(span1.data(), span2.data(), span2.size())) ==
+               0;
       }
       case CPDF_Object::kReference:
         return obj1->AsReference()->GetRefObjNum() ==
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index 3e8a13a..a15c47e 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -295,7 +295,8 @@
 
 FX_FILESIZE CPDF_Parser::ParseStartXRef() {
   static constexpr char kStartXRefKeyword[] = "startxref";
-  m_pSyntax->SetPos(m_pSyntax->GetDocumentSize() - strlen(kStartXRefKeyword));
+  m_pSyntax->SetPos(m_pSyntax->GetDocumentSize() -
+                    UNSAFE_TODO(strlen(kStartXRefKeyword)));
   if (!m_pSyntax->BackwardsSearchToWord(kStartXRefKeyword, 4096))
     return 0;
 
diff --git a/core/fpdfapi/parser/cpdf_security_handler.cpp b/core/fpdfapi/parser/cpdf_security_handler.cpp
index 4e87fd8..ec62240 100644
--- a/core/fpdfapi/parser/cpdf_security_handler.cpp
+++ b/core/fpdfapi/parser/cpdf_security_handler.cpp
@@ -347,8 +347,9 @@
     }
     CRYPT_SHA256Finish(&sha, digest);
   }
-  if (memcmp(digest, pkey, 32) != 0)
+  if (UNSAFE_TODO(FXSYS_memcmp(digest, pkey, 32)) != 0) {
     return false;
+  }
 
   if (m_Revision >= 6) {
     Revision6_Hash(password, UNSAFE_TODO(pkey + 40),
@@ -456,7 +457,7 @@
         FXSYS_memcpy(ukeybuf, kDefaultPasscode, sizeof(kDefaultPasscode)));
     CRYPT_ArcFourCryptBlock(ukeybuf,
                             pdfium::make_span(m_EncryptKey).first(m_KeyLen));
-    return memcmp(ukey.c_str(), ukeybuf, 16) == 0;
+    return UNSAFE_TODO(memcmp(ukey.c_str(), ukeybuf, 16)) == 0;
   }
 
   uint8_t test[32] = {};
@@ -474,7 +475,7 @@
   if (!m_FileId.IsEmpty())
     CRYPT_MD5Update(&md5, m_FileId.unsigned_span());
   CRYPT_MD5Finish(&md5, pdfium::make_span(ukeybuf).first(16u));
-  return memcmp(test, ukeybuf, 16) == 0;
+  return UNSAFE_TODO(memcmp(test, ukeybuf, 16)) == 0;
 }
 
 ByteString CPDF_SecurityHandler::GetUserPassword(
diff --git a/core/fpdfapi/parser/cpdf_seekablemultistream_unittest.cpp b/core/fpdfapi/parser/cpdf_seekablemultistream_unittest.cpp
index fa36d39..5d6942c 100644
--- a/core/fpdfapi/parser/cpdf_seekablemultistream_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_seekablemultistream_unittest.cpp
@@ -73,21 +73,21 @@
   fxcrt::Fill(output_buffer, 0xbd);
   EXPECT_TRUE(fileread->ReadBlockAtOffset(
       pdfium::make_span(output_buffer).first(1u), 0));
-  EXPECT_EQ(0, memcmp(output_buffer, "o", 1));
+  EXPECT_EQ(0, UNSAFE_TODO(memcmp(output_buffer, "o", 1)));
   EXPECT_EQ(0xbd, output_buffer[1]);
 
   fxcrt::Fill(output_buffer, 0xbd);
   EXPECT_TRUE(fileread->ReadBlockAtOffset(output_buffer, 0));
-  EXPECT_EQ(0, memcmp(output_buffer, "one two three!!!", 16));
+  EXPECT_EQ(0, UNSAFE_TODO(memcmp(output_buffer, "one two three!!!", 16)));
 
   fxcrt::Fill(output_buffer, 0xbd);
   EXPECT_TRUE(fileread->ReadBlockAtOffset(
       pdfium::make_span(output_buffer).first(10u), 2));
-  EXPECT_EQ(0, memcmp(output_buffer, "e two thre", 10));
+  EXPECT_EQ(0, UNSAFE_TODO(memcmp(output_buffer, "e two thre", 10)));
   EXPECT_EQ(0xbd, output_buffer[11]);
 
   fxcrt::Fill(output_buffer, 0xbd);
   EXPECT_FALSE(fileread->ReadBlockAtOffset(output_buffer, 1));
-  EXPECT_EQ(0, memcmp(output_buffer, "ne two three!!!", 15));
+  EXPECT_EQ(0, UNSAFE_TODO(memcmp(output_buffer, "ne two three!!!", 15)));
   EXPECT_EQ(0xbd, output_buffer[15]);
 }
diff --git a/core/fpdfapi/parser/cpdf_syntax_parser.cpp b/core/fpdfapi/parser/cpdf_syntax_parser.cpp
index b8d1a19..f252339 100644
--- a/core/fpdfapi/parser/cpdf_syntax_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_syntax_parser.cpp
@@ -761,8 +761,9 @@
     // Earlier version of PDF specification doesn't require EOL marker before
     // 'endstream' keyword. If keyword 'endstream' follows the bytes in
     // specified length, it signals the end of stream.
-    if (memcmp(m_WordBuffer.data(), kEndStreamStr.unterminated_unsigned_str(),
-               kEndStreamStr.GetLength()) != 0) {
+    if (UNSAFE_TODO(memcmp(m_WordBuffer.data(),
+                           kEndStreamStr.unterminated_unsigned_str(),
+                           kEndStreamStr.GetLength())) != 0) {
       substream.Reset();
       len = -1;
       SetPos(streamStartPos);
@@ -827,8 +828,9 @@
   int numMarkers = ReadEOLMarkers(GetPos());
   if (m_WordSize == static_cast<unsigned int>(kEndObjStr.GetLength()) &&
       numMarkers != 0 &&
-      memcmp(m_WordBuffer.data(), kEndObjStr.unterminated_unsigned_str(),
-             kEndObjStr.GetLength()) == 0) {
+      UNSAFE_TODO(memcmp(m_WordBuffer.data(),
+                         kEndObjStr.unterminated_unsigned_str(),
+                         kEndObjStr.GetLength())) == 0) {
     SetPos(end_stream_offset);
   }
   return stream;
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.cpp b/core/fpdfapi/parser/fpdf_parser_utility.cpp
index 441dfd1..04e998d 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_utility.cpp
@@ -19,6 +19,7 @@
 #include "core/fpdfapi/parser/cpdf_string.h"
 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
 #include "core/fxcrt/check.h"
+#include "core/fxcrt/compiler_specific.h"
 #include "core/fxcrt/fx_extension.h"
 #include "core/fxcrt/fx_stream.h"
 
@@ -82,8 +83,10 @@
     if (!pFile->ReadBlockAtOffset(buf, offset))
       return std::nullopt;
 
-    if (memcmp(buf, "%PDF", 4) == 0)
+    // SAFETY: string literal and `buf` can accommodate 4 byte comparisons.
+    if (UNSAFE_BUFFERS(memcmp(buf, "%PDF", 4)) == 0) {
       return offset;
+    }
   }
   return std::nullopt;
 }
diff --git a/core/fpdfdoc/cpdf_interactiveform.cpp b/core/fpdfdoc/cpdf_interactiveform.cpp
index 497551a..16a5a62 100644
--- a/core/fpdfdoc/cpdf_interactiveform.cpp
+++ b/core/fpdfdoc/cpdf_interactiveform.cpp
@@ -140,9 +140,10 @@
   const size_t szCount = csStr.GetLength();
   size_t m = 0;
   ByteString csTmp;
-  while (m < strlen(kDummyFontName) && m < szCount)
+  while (m < UNSAFE_TODO(strlen(kDummyFontName)) && m < szCount) {
     csTmp += csStr[m++];
-  while (m < strlen(kDummyFontName)) {
+  }
+  while (m < UNSAFE_TODO(strlen(kDummyFontName))) {
     csTmp += '0' + m % 10;
     m++;
   }
diff --git a/core/fpdftext/cpdf_linkextract.cpp b/core/fpdftext/cpdf_linkextract.cpp
index 53d16bd..341b674 100644
--- a/core/fpdftext/cpdf_linkextract.cpp
+++ b/core/fpdftext/cpdf_linkextract.cpp
@@ -180,19 +180,15 @@
 
 std::optional<CPDF_LinkExtract::Link> CPDF_LinkExtract::CheckWebLink(
     const WideString& strBeCheck) {
-  static const wchar_t kHttpScheme[] = L"http";
-  static const wchar_t kWWWAddrStart[] = L"www.";
-
-  const size_t kHttpSchemeLen = wcslen(kHttpScheme);
-  const size_t kWWWAddrStartLen = wcslen(kWWWAddrStart);
-
+  const WideStringView kHttpScheme = L"http";
+  const WideStringView kWWWAddrStart = L"www.";
   WideString str = strBeCheck;
   str.MakeLower();
 
   // First, try to find the scheme.
   auto start = str.Find(kHttpScheme);
   if (start.has_value()) {
-    size_t off = start.value() + kHttpSchemeLen;  // move after "http".
+    size_t off = start.value() + kHttpScheme.GetLength();  // move after "http".
     if (str.GetLength() > off + 4) {  // At least "://<char>" follows.
       if (str[off] == L's')  // "https" scheme is accepted.
         off++;
@@ -214,7 +210,7 @@
   // When there is no scheme, try to find url starting with "www.".
   start = str.Find(kWWWAddrStart);
   if (start.has_value()) {
-    size_t off = start.value() + kWWWAddrStartLen;
+    size_t off = start.value() + kWWWAddrStart.GetLength();
     if (str.GetLength() > off) {
       const size_t end =
           FindWebLinkEnding(str, start.value(),
diff --git a/core/fxcodec/fax/faxmodule.cpp b/core/fxcodec/fax/faxmodule.cpp
index 593202f..2fe0c2d 100644
--- a/core/fxcodec/fax/faxmodule.cpp
+++ b/core/fxcodec/fax/faxmodule.cpp
@@ -90,8 +90,8 @@
         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
     const uint8_t* skip_block = bit ? skip_block_0 : skip_block_1;
     while (byte_pos < max_byte - kBulkReadSize &&
-           memcmp(data_buf.subspan(byte_pos).data(), skip_block,
-                  kBulkReadSize) == 0) {
+           UNSAFE_TODO(memcmp(data_buf.subspan(byte_pos).data(), skip_block,
+                              kBulkReadSize)) == 0) {
       byte_pos += kBulkReadSize;
     }
   }
diff --git a/core/fxcodec/gif/cfx_gifcontext.cpp b/core/fxcodec/gif/cfx_gifcontext.cpp
index 993d545..aa64063 100644
--- a/core/fxcodec/gif/cfx_gifcontext.cpp
+++ b/core/fxcodec/gif/cfx_gifcontext.cpp
@@ -343,11 +343,10 @@
   if (!ReadAllOrNone(pdfium::byte_span_from_ref(header))) {
     return GifDecoder::Status::kUnfinished;
   }
-  if (strncmp(header.signature, kGifSignature87, 6) != 0 &&
-      strncmp(header.signature, kGifSignature89, 6) != 0) {
+  if (UNSAFE_TODO(strncmp(header.signature, kGifSignature87, 6)) != 0 &&
+      UNSAFE_TODO(strncmp(header.signature, kGifSignature89, 6)) != 0) {
     return GifDecoder::Status::kError;
   }
-
   return GifDecoder::Status::kSuccess;
 }
 
diff --git a/core/fxcodec/gif/cfx_gifcontext_unittest.cpp b/core/fxcodec/gif/cfx_gifcontext_unittest.cpp
index f5a626a..9c75577 100644
--- a/core/fxcodec/gif/cfx_gifcontext_unittest.cpp
+++ b/core/fxcodec/gif/cfx_gifcontext_unittest.cpp
@@ -207,8 +207,9 @@
     EXPECT_EQ(1u, context.global_palette_exp_);
     EXPECT_EQ(1, context.global_sort_flag_);
     EXPECT_EQ(2, context.global_color_resolution_);
-    EXPECT_EQ(0, memcmp(data.palette, context.global_palette_.data(),
-                        sizeof(data.palette)));
+    EXPECT_EQ(0,
+              UNSAFE_TODO(memcmp(data.palette, context.global_palette_.data(),
+                                 sizeof(data.palette))));
     context.SetTestInputBuffer({});
   }
 }
@@ -280,8 +281,9 @@
     EXPECT_EQ(1u, context.global_palette_exp_);
     EXPECT_EQ(1, context.global_sort_flag_);
     EXPECT_EQ(2, context.global_color_resolution_);
-    EXPECT_EQ(0, memcmp(data.palette, context.global_palette_.data(),
-                        sizeof(data.palette)));
+    EXPECT_EQ(0,
+              UNSAFE_TODO(memcmp(data.palette, context.global_palette_.data(),
+                                 sizeof(data.palette))));
     context.SetTestInputBuffer({});
   }
 }
diff --git a/core/fxcodec/gif/lzw_decompressor_unittest.cpp b/core/fxcodec/gif/lzw_decompressor_unittest.cpp
index d11e1be..edb7ff5 100644
--- a/core/fxcodec/gif/lzw_decompressor_unittest.cpp
+++ b/core/fxcodec/gif/lzw_decompressor_unittest.cpp
@@ -127,7 +127,8 @@
             UNSAFE_TODO(decompressor->Decode(output_data, &output_size)));
 
   EXPECT_EQ(std::size(output_data), output_size);
-  EXPECT_TRUE(0 == memcmp(expected_data, output_data, sizeof(expected_data)));
+  EXPECT_TRUE(0 == UNSAFE_TODO(memcmp(expected_data, output_data,
+                                      sizeof(expected_data))));
 }
 
 TEST(LZWDecompressor, Decode10x10SingleColour) {
@@ -156,7 +157,8 @@
             UNSAFE_TODO(decompressor->Decode(output_data, &output_size)));
 
   EXPECT_EQ(std::size(output_data), output_size);
-  EXPECT_TRUE(0 == memcmp(kExpectedData, output_data, sizeof(kExpectedData)));
+  EXPECT_TRUE(0 == UNSAFE_TODO(memcmp(kExpectedData, output_data,
+                                      sizeof(kExpectedData))));
 }
 
 TEST(LZWDecompressor, Decode10x10MultipleColour) {
@@ -186,7 +188,8 @@
             UNSAFE_TODO(decompressor->Decode(output_data, &output_size)));
 
   EXPECT_EQ(std::size(output_data), output_size);
-  EXPECT_TRUE(0 == memcmp(kExpectedData, output_data, sizeof(kExpectedData)));
+  EXPECT_TRUE(0 == UNSAFE_TODO(memcmp(kExpectedData, output_data,
+                                      sizeof(kExpectedData))));
 }
 
 TEST(LZWDecompressor, MultipleDecodes) {
diff --git a/core/fxcodec/jpx/cjpx_decoder.cpp b/core/fxcodec/jpx/cjpx_decoder.cpp
index 90f729b..4d2e269 100644
--- a/core/fxcodec/jpx/cjpx_decoder.cpp
+++ b/core/fxcodec/jpx/cjpx_decoder.cpp
@@ -454,7 +454,8 @@
   m_Parameters.decod_format = 0;
   m_Parameters.cod_format = 3;
   m_Parameters.cp_reduce = resolution_levels_to_skip;
-  if (memcmp(m_SrcData.data(), kJP2Header, sizeof(kJP2Header)) == 0) {
+  if (UNSAFE_TODO(memcmp(m_SrcData.data(), kJP2Header, sizeof(kJP2Header))) ==
+      0) {
     m_Codec.reset(opj_create_decompress(OPJ_CODEC_JP2));
     m_Parameters.decod_format = 1;
   } else {
diff --git a/core/fxcodec/png/png_decoder.cpp b/core/fxcodec/png/png_decoder.cpp
index 34d5a26..0e42317 100644
--- a/core/fxcodec/png/png_decoder.cpp
+++ b/core/fxcodec/png/png_decoder.cpp
@@ -12,6 +12,7 @@
 #include "core/fxcodec/cfx_codec_memory.h"
 #include "core/fxcodec/fx_codec.h"
 #include "core/fxcodec/fx_codec_def.h"
+#include "core/fxcrt/compiler_specific.h"
 #include "core/fxcrt/unowned_ptr.h"
 
 #ifdef USE_SYSTEM_LIBPNG
@@ -37,8 +38,8 @@
 
 void _png_error_data(png_structp png_ptr, png_const_charp error_msg) {
   if (png_get_error_ptr(png_ptr)) {
-    strncpy(static_cast<char*>(png_get_error_ptr(png_ptr)), error_msg,
-            PNG_ERROR_SIZE - 1);
+    UNSAFE_TODO(strncpy(static_cast<char*>(png_get_error_ptr(png_ptr)),
+                        error_msg, PNG_ERROR_SIZE - 1));
   }
 
   longjmp(png_jmpbuf(png_ptr), 1);
@@ -228,8 +229,8 @@
   pdfium::span<uint8_t> src_buf = codec_memory->GetUnconsumedSpan();
   if (!_png_continue_decode(ctx->m_pPng, ctx->m_pInfo, src_buf.data(),
                             src_buf.size())) {
-    if (pAttribute &&
-        strcmp(ctx->m_szLastError, "Read Header Callback Error") == 0) {
+    if (pAttribute && UNSAFE_TODO(strcmp(ctx->m_szLastError,
+                                         "Read Header Callback Error")) == 0) {
       _png_load_bmp_attribute(ctx->m_pPng, ctx->m_pInfo, pAttribute);
     }
     return false;
diff --git a/core/fxcrt/bytestring.cpp b/core/fxcrt/bytestring.cpp
index 7db94bc..8b358f0 100644
--- a/core/fxcrt/bytestring.cpp
+++ b/core/fxcrt/bytestring.cpp
@@ -16,6 +16,7 @@
 
 #include "core/fxcrt/check.h"
 #include "core/fxcrt/check_op.h"
+#include "core/fxcrt/compiler_specific.h"
 #include "core/fxcrt/fx_codepage.h"
 #include "core/fxcrt/fx_extension.h"
 #include "core/fxcrt/fx_memcpy_wrappers.h"
@@ -49,10 +50,13 @@
 }
 
 // static
+// TODO(tsepez): Should be UNSAFE_BUFFER_USAGE.
 ByteString ByteString::FormatV(const char* pFormat, va_list argList) {
   va_list argListCopy;
   va_copy(argListCopy, argList);
-  int nMaxLen = vsnprintf(nullptr, 0, pFormat, argListCopy);
+
+  // SAFETY: required from caller.
+  int nMaxLen = UNSAFE_BUFFERS(vsnprintf(nullptr, 0, pFormat, argListCopy));
   va_end(argListCopy);
 
   if (nMaxLen <= 0)
@@ -68,7 +72,7 @@
     // included in the span.
     UNSAFE_BUFFERS(FXSYS_memset(buf.data(), 0, nMaxLen + 1));
     va_copy(argListCopy, argList);
-    vsnprintf(buf.data(), nMaxLen + 1, pFormat, argListCopy);
+    UNSAFE_TODO(vsnprintf(buf.data(), nMaxLen + 1, pFormat, argListCopy));
     va_end(argListCopy);
   }
   ret.ReleaseBuffer(ret.GetStringLength());
@@ -149,12 +153,14 @@
   }
 }
 
+// TODO(tsepez): Should be UNSAFE_BUFFER_USAGE.
 ByteString& ByteString::operator=(const char* str) {
-  if (!str || !str[0])
+  if (!str || !str[0]) {
     clear();
-  else
-    AssignCopy(str, strlen(str));
-
+  } else {
+    // SAFETY: required from caller.
+    AssignCopy(str, UNSAFE_BUFFERS(strlen(str)));
+  }
   return *this;
 }
 
@@ -181,10 +187,12 @@
   return *this;
 }
 
+// TODO(tsepez): Should be UNSAFE_BUFFER_USAGE
 ByteString& ByteString::operator+=(const char* str) {
-  if (str)
-    Concat(str, strlen(str));
-
+  if (str) {
+    // SAFETY: required from caller.
+    Concat(str, UNSAFE_BUFFERS(strlen(str)));
+  }
   return *this;
 }
 
@@ -207,6 +215,7 @@
   return *this;
 }
 
+// TODO(tsepez): Should be UNSAFE_BUFFER_USAGE
 bool ByteString::operator==(const char* ptr) const {
   if (!m_pData)
     return !ptr || !ptr[0];
@@ -215,8 +224,9 @@
     return m_pData->m_nDataLength == 0;
 
   // SAFETY: `m_nDataLength` is within `m_String`, and the strlen() call
-  // ensures there are `m_nDataLength` bytes at `ptr` before the terminator.
-  return strlen(ptr) == m_pData->m_nDataLength &&
+  // (whose own safety is required from the caller) ensures there are
+  // `m_nDataLength` bytes at `ptr` before the terminator.
+  return UNSAFE_BUFFERS(strlen(ptr)) == m_pData->m_nDataLength &&
          UNSAFE_BUFFERS(
              FXSYS_memcmp(ptr, m_pData->m_String, m_pData->m_nDataLength)) == 0;
 }
@@ -234,28 +244,34 @@
 }
 
 bool ByteString::operator==(const ByteString& other) const {
-  if (m_pData == other.m_pData)
+  if (m_pData == other.m_pData) {
     return true;
-
-  if (IsEmpty())
+  }
+  if (IsEmpty()) {
     return other.IsEmpty();
-
-  if (other.IsEmpty())
+  }
+  if (other.IsEmpty()) {
     return false;
+  }
 
+  // SAFETY: m_nDataLength describes the length of m_String.
   return other.m_pData->m_nDataLength == m_pData->m_nDataLength &&
-         memcmp(other.m_pData->m_String, m_pData->m_String,
-                m_pData->m_nDataLength) == 0;
+         UNSAFE_BUFFERS(memcmp(other.m_pData->m_String, m_pData->m_String,
+                               m_pData->m_nDataLength)) == 0;
 }
 
+// TODO(tsepez): Should be UNSAFE_BUFFER_USAGE.
 bool ByteString::operator<(const char* ptr) const {
-  if (!m_pData && !ptr)
+  if (!m_pData && !ptr) {
     return false;
-  if (c_str() == ptr)
+  }
+  if (c_str() == ptr) {
     return false;
+  }
 
+  // SAFETY: required from caller.
+  size_t other_len = ptr ? UNSAFE_BUFFERS(strlen(ptr)) : 0;
   size_t len = GetLength();
-  size_t other_len = ptr ? strlen(ptr) : 0;
 
   // SAFETY: Comparison limited to minimum valid length of either argument.
   int result =
diff --git a/core/fxcrt/bytestring_unittest.cpp b/core/fxcrt/bytestring_unittest.cpp
index 398749c..793ab36 100644
--- a/core/fxcrt/bytestring_unittest.cpp
+++ b/core/fxcrt/bytestring_unittest.cpp
@@ -39,21 +39,22 @@
 
   pdfium::span<const char> abc_span = abc.span();
   EXPECT_EQ(3u, abc_span.size());
-  EXPECT_EQ(0, memcmp(abc_span.data(), "abc", 3));
+  EXPECT_EQ(0, UNSAFE_TODO(memcmp(abc_span.data(), "abc", 3)));
 
   pdfium::span<const char> abc_span_with_terminator =
       abc.span_with_terminator();
   EXPECT_EQ(4u, abc_span_with_terminator.size());
-  EXPECT_EQ(0, memcmp(abc_span_with_terminator.data(), "abc", 4));
+  EXPECT_EQ(0, UNSAFE_TODO(memcmp(abc_span_with_terminator.data(), "abc", 4)));
 
   pdfium::span<const uint8_t> abc_raw_span = abc.unsigned_span();
   EXPECT_EQ(3u, abc_raw_span.size());
-  EXPECT_EQ(0, memcmp(abc_raw_span.data(), "abc", 3));
+  EXPECT_EQ(0, UNSAFE_TODO(memcmp(abc_raw_span.data(), "abc", 3)));
 
   pdfium::span<const uint8_t> abc_raw_span_with_terminator =
       abc.unsigned_span_with_terminator();
   EXPECT_EQ(4u, abc_raw_span_with_terminator.size());
-  EXPECT_EQ(0, memcmp(abc_raw_span_with_terminator.data(), "abc", 4));
+  EXPECT_EQ(0,
+            UNSAFE_TODO(memcmp(abc_raw_span_with_terminator.data(), "abc", 4)));
 
   ByteString mutable_abc = abc;
   EXPECT_EQ(abc.c_str(), mutable_abc.c_str());
@@ -1027,8 +1028,9 @@
   ByteString str1;
   {
     pdfium::span<char> buffer = str1.GetBuffer(12);
+    // SAFETY: required for test.
     // NOLINTNEXTLINE(runtime/printf)
-    strcpy(buffer.data(), "clams");
+    UNSAFE_BUFFERS(strcpy(buffer.data(), "clams"));
   }
   str1.ReleaseBuffer(str1.GetStringLength());
   EXPECT_EQ("clams", str1);
@@ -1036,8 +1038,9 @@
   ByteString str2("cl");
   {
     pdfium::span<char> buffer = str2.GetBuffer(12);
+    // SAFETY: required for test.
     // NOLINTNEXTLINE(runtime/printf)
-    strcpy(&buffer[2], "ams");
+    UNSAFE_BUFFERS(strcpy(&buffer[2], "ams"));
   }
   str2.ReleaseBuffer(str2.GetStringLength());
   EXPECT_EQ("clams", str2);
@@ -1756,7 +1759,7 @@
 
   const char* cstr = empty_str.c_str();
   EXPECT_TRUE(cstr);
-  EXPECT_EQ(0u, strlen(cstr));
+  EXPECT_EQ(0u, UNSAFE_TODO(strlen(cstr)));
 
   const uint8_t* rstr = empty_str.unsigned_str();
   EXPECT_FALSE(rstr);
diff --git a/core/fxcrt/fx_extension.cpp b/core/fxcrt/fx_extension.cpp
index 45393e6..0db87cd 100644
--- a/core/fxcrt/fx_extension.cpp
+++ b/core/fxcrt/fx_extension.cpp
@@ -36,7 +36,8 @@
   // Force NUL-termination via copied buffer.
   auto copied = WideString(pwsStr);
   wchar_t* endptr = nullptr;
-  float result = wcstof(copied.c_str(), &endptr);
+  // SAFETY: WideStrings are NUL-terminated.
+  float result = UNSAFE_BUFFERS(wcstof(copied.c_str(), &endptr));
   if (result != result) {
     result = 0.0f;  // Convert NAN to 0.0f;
   }
diff --git a/core/fxcrt/fx_stream.cpp b/core/fxcrt/fx_stream.cpp
index 3a5a307..9a0a00a 100644
--- a/core/fxcrt/fx_stream.cpp
+++ b/core/fxcrt/fx_stream.cpp
@@ -55,13 +55,16 @@
   char buf[20] = {};
   FXSYS_itoa(i, buf, 10);
   auto buf_span = pdfium::as_byte_span(buf);
-  return WriteBlock(buf_span.first(strlen(buf)));
+  // SAFETY: itoa() terminates buf.
+  return WriteBlock(buf_span.first(UNSAFE_BUFFERS(strlen(buf))));
 }
 
 bool IFX_WriteStream::WriteFilesize(FX_FILESIZE size) {
   char buf[20] = {};
   FXSYS_i64toa(size, buf, 10);
-  return WriteBlock(pdfium::as_writable_byte_span(buf).first(strlen(buf)));
+  auto buf_span = pdfium::as_byte_span(buf);
+  // SAFETY: itoa() terminates buf.
+  return WriteBlock(buf_span.first(UNSAFE_BUFFERS(strlen(buf))));
 }
 
 // static
diff --git a/core/fxcrt/widestring.cpp b/core/fxcrt/widestring.cpp
index 0909cc6..f026326 100644
--- a/core/fxcrt/widestring.cpp
+++ b/core/fxcrt/widestring.cpp
@@ -15,6 +15,7 @@
 
 #include "core/fxcrt/check.h"
 #include "core/fxcrt/check_op.h"
+#include "core/fxcrt/compiler_specific.h"
 #include "core/fxcrt/fx_codepage.h"
 #include "core/fxcrt/fx_extension.h"
 #include "core/fxcrt/fx_memcpy_wrappers.h"
@@ -149,7 +150,7 @@
       case 's': {
         const wchar_t* pstrNextArg = va_arg(argList, const wchar_t*);
         if (pstrNextArg) {
-          nItemLen = wcslen(pstrNextArg);
+          nItemLen = UNSAFE_TODO(wcslen(pstrNextArg));
           if (nItemLen < 1) {
             nItemLen = 1;
           }
@@ -160,7 +161,7 @@
       case 'S': {
         const char* pstrNextArg = va_arg(argList, const char*);
         if (pstrNextArg) {
-          nItemLen = strlen(pstrNextArg);
+          nItemLen = UNSAFE_TODO(strlen(pstrNextArg));
           if (nItemLen < 1) {
             nItemLen = 1;
           }
@@ -172,7 +173,7 @@
       case 'S' | FORCE_ANSI: {
         const char* pstrNextArg = va_arg(argList, const char*);
         if (pstrNextArg) {
-          nItemLen = strlen(pstrNextArg);
+          nItemLen = UNSAFE_TODO(strlen(pstrNextArg));
           if (nItemLen < 1) {
             nItemLen = 1;
           }
@@ -184,7 +185,7 @@
       case 'S' | FORCE_UNICODE: {
         const wchar_t* pstrNextArg = va_arg(argList, wchar_t*);
         if (pstrNextArg) {
-          nItemLen = wcslen(pstrNextArg);
+          nItemLen = UNSAFE_TODO(wcslen(pstrNextArg));
           if (nItemLen < 1) {
             nItemLen = 1;
           }
@@ -239,7 +240,7 @@
             f = va_arg(argList, double);
             FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth,
                            nPrecision + 6, f);
-            nItemLen = strlen(pszTemp);
+            nItemLen = UNSAFE_TODO(strlen(pszTemp));
           }
           break;
         case 'p':
@@ -280,7 +281,7 @@
     // See https://crbug.com/705912.
     UNSAFE_BUFFERS(
         FXSYS_memset(buffer.data(), 0, (size + 1) * sizeof(wchar_t)));
-    int ret = vswprintf(buffer.data(), size + 1, pFormat, argList);
+    int ret = UNSAFE_TODO(vswprintf(buffer.data(), size + 1, pFormat, argList));
     bool bSufficientBuffer = ret >= 0 || buffer[size - 1] == 0;
     if (!bSufficientBuffer)
       return std::nullopt;
@@ -359,7 +360,8 @@
 // static
 WideString WideString::FormatInteger(int i) {
   wchar_t wbuf[32];
-  swprintf(wbuf, std::size(wbuf), L"%d", i);
+  // SAFTEY: 32 bytes accommodates biggest int representation plus NUL.
+  UNSAFE_BUFFERS(swprintf(wbuf, std::size(wbuf), L"%d", i));
   return WideString(wbuf);
 }
 
@@ -450,12 +452,14 @@
   }
 }
 
+// Should be UNSAFE_BUFFER_USAGE.
 WideString& WideString::operator=(const wchar_t* str) {
-  if (!str || !str[0])
+  if (!str || !str[0]) {
     clear();
-  else
-    AssignCopy(str, wcslen(str));
-
+  } else {
+    // SAFETY: required from caller.
+    AssignCopy(str, UNSAFE_BUFFERS(wcslen(str)));
+  }
   return *this;
 }
 
@@ -482,10 +486,12 @@
   return *this;
 }
 
+// Should be UNSAFE_BUFFER_USAGE.
 WideString& WideString::operator+=(const wchar_t* str) {
-  if (str)
-    Concat(str, wcslen(str));
-
+  if (str) {
+    // SAFETY: required from caller.
+    Concat(str, UNSAFE_BUFFERS(wcslen(str)));
+  }
   return *this;
 }
 
@@ -508,16 +514,19 @@
   return *this;
 }
 
+// Should be UNSAFE_BUFFER_USAGE.
 bool WideString::operator==(const wchar_t* ptr) const {
-  if (!m_pData)
+  if (!m_pData) {
     return !ptr || !ptr[0];
-
-  if (!ptr)
+  }
+  if (!ptr) {
     return m_pData->m_nDataLength == 0;
+  }
 
-  // SAFTEY: `wsclen()` comparison ensures there are `m_nDataLength` wchars at
-  // `ptr` before the terminator, and `m_nDataLength` is within `m_String`.
-  return wcslen(ptr) == m_pData->m_nDataLength &&
+  // SAFTEY: `wsclen()` comparison (whose own safety depends upoon the caller)
+  // ensures there are `m_nDataLength` wchars at `ptr` before the terminator,
+  // and `m_nDataLength` is within `m_String`.
+  return UNSAFE_BUFFERS(wcslen(ptr)) == m_pData->m_nDataLength &&
          UNSAFE_BUFFERS(FXSYS_wmemcmp(ptr, m_pData->m_String,
                                       m_pData->m_nDataLength)) == 0;
 }
@@ -544,9 +553,11 @@
   if (other.IsEmpty())
     return false;
 
+  // SAFETY: m_nDataLength bytes available at m_String.
   return other.m_pData->m_nDataLength == m_pData->m_nDataLength &&
-         wmemcmp(other.m_pData->m_String, m_pData->m_String,
-                 m_pData->m_nDataLength) == 0;
+         UNSAFE_BUFFERS(FXSYS_wmemcmp(other.m_pData->m_String,
+                                      m_pData->m_String,
+                                      m_pData->m_nDataLength)) == 0;
 }
 
 bool WideString::operator<(const wchar_t* ptr) const {
@@ -790,9 +801,12 @@
   return result;
 }
 
+// Should be UNSAFE_BUFFER_USAGE/
 int WideString::Compare(const wchar_t* str) const {
-  if (m_pData)
-    return str ? wcscmp(m_pData->m_String, str) : 1;
+  if (m_pData) {
+    // SAFETY: required from caller.
+    return str ? UNSAFE_BUFFERS(wcscmp(m_pData->m_String, str)) : 1;
+  }
   return (!str || str[0] == 0) ? 0 : -1;
 }
 
diff --git a/core/fxcrt/widestring_unittest.cpp b/core/fxcrt/widestring_unittest.cpp
index 885b4cf..1ac37f9 100644
--- a/core/fxcrt/widestring_unittest.cpp
+++ b/core/fxcrt/widestring_unittest.cpp
@@ -39,12 +39,13 @@
 
   pdfium::span<const wchar_t> abc_span = abc.span();
   EXPECT_EQ(3u, abc_span.size());
-  EXPECT_EQ(0, wmemcmp(abc_span.data(), L"abc", 3));
+  EXPECT_EQ(0, UNSAFE_TODO(wmemcmp(abc_span.data(), L"abc", 3)));
 
   pdfium::span<const wchar_t> abc_span_with_terminator =
       abc.span_with_terminator();
   EXPECT_EQ(4u, abc_span_with_terminator.size());
-  EXPECT_EQ(0, wmemcmp(abc_span_with_terminator.data(), L"abc", 4));
+  EXPECT_EQ(0,
+            UNSAFE_TODO(wmemcmp(abc_span_with_terminator.data(), L"abc", 4)));
 
   WideString mutable_abc = abc;
   EXPECT_EQ(abc.c_str(), mutable_abc.c_str());
@@ -1015,7 +1016,8 @@
   WideString str1;
   {
     pdfium::span<wchar_t> buffer = str1.GetBuffer(12);
-    wcscpy(buffer.data(), L"clams");
+    // SAFETY: required for test.
+    UNSAFE_BUFFERS(wcscpy(buffer.data(), L"clams"));
   }
   str1.ReleaseBuffer(str1.GetStringLength());
   EXPECT_EQ(L"clams", str1);
@@ -1885,7 +1887,7 @@
 
   const wchar_t* cstr = empty_str.c_str();
   EXPECT_TRUE(cstr);
-  EXPECT_EQ(0u, wcslen(cstr));
+  EXPECT_EQ(0u, UNSAFE_TODO(wcslen(cstr)));
 
   pdfium::span<const wchar_t> cspan = empty_str.span();
   EXPECT_TRUE(cspan.empty());
diff --git a/core/fxge/cfx_folderfontinfo.cpp b/core/fxge/cfx_folderfontinfo.cpp
index cda0141..af936b9 100644
--- a/core/fxge/cfx_folderfontinfo.cpp
+++ b/core/fxge/cfx_folderfontinfo.cpp
@@ -80,8 +80,11 @@
   {
     // Span's lifetime must end before ReleaseBuffer() below.
     pdfium::span<char> buffer = result.GetBuffer(size);
-    if (!fread(buffer.data(), size, 1, pFile))
+
+    // SAFETY: GetBuffer(size) ensures size bytes available.
+    if (!UNSAFE_BUFFERS(fread(buffer.data(), size, 1, pFile))) {
       return ByteString();
+    }
   }
   result.ReleaseBuffer(size);
   return result;
@@ -189,7 +192,9 @@
   uint8_t buffer[16];
   fseek(pFile.get(), 0, SEEK_SET);
 
-  size_t items_read = fread(buffer, /*size=*/12, /*nmemb=*/1, pFile.get());
+  // SAFETY: 12 byte read fits into 16 byte buffer,
+  size_t items_read =
+      UNSAFE_BUFFERS(fread(buffer, /*size=*/12, /*nmemb=*/1, pFile.get()));
   if (items_read != 1) {
     return;
   }
@@ -210,8 +215,8 @@
   auto offsets =
       FixedSizeDataVector<uint8_t>::Uninit(safe_face_bytes.ValueOrDie());
   pdfium::span<uint8_t> offsets_span = offsets.span();
-  items_read = fread(offsets_span.data(), /*size=*/1,
-                     /*nmemb=*/offsets_span.size(), pFile.get());
+  items_read = UNSAFE_TODO(fread(offsets_span.data(), /*size=*/1,
+                                 /*nmemb=*/offsets_span.size(), pFile.get()));
   if (items_read != offsets_span.size()) {
     return;
   }
@@ -227,8 +232,13 @@
                                     FX_FILESIZE filesize,
                                     uint32_t offset) {
   char buffer[16];
-  if (fseek(pFile, offset, SEEK_SET) < 0 || !fread(buffer, 12, 1, pFile))
+  if (fseek(pFile, offset, SEEK_SET) < 0) {
     return;
+  }
+  // SAFTEY: 12 byt read fits in 16 byte buffer.
+  if (UNSAFE_BUFFERS(!fread(buffer, 12, 1, pFile))) {
+    return;
+  }
 
   uint32_t nTables =
       fxcrt::GetUInt16MSBFirst(pdfium::as_byte_span(buffer).subspan<4, 2>());
@@ -417,8 +427,10 @@
   if (!pFile)
     return 0;
 
-  if (fseek(pFile.get(), offset, SEEK_SET) < 0 ||
-      fread(buffer.data(), datasize, 1, pFile.get()) != 1) {
+  if (fseek(pFile.get(), offset, SEEK_SET) < 0) {
+    return 0;
+  }
+  if (UNSAFE_TODO(fread(buffer.data(), datasize, 1, pFile.get())) != 1) {
     return 0;
   }
   return datasize;
diff --git a/fpdfsdk/cpdfsdk_helpers.cpp b/fpdfsdk/cpdfsdk_helpers.cpp
index c1cf7d4..eb74519 100644
--- a/fpdfsdk/cpdfsdk_helpers.cpp
+++ b/fpdfsdk/cpdfsdk_helpers.cpp
@@ -520,16 +520,21 @@
   for (const auto& entry : fxcrt::Split(bsStrippedPageRange, ',')) {
     std::vector<ByteString> args = fxcrt::Split(entry, '-');
     if (args.size() == 1) {
-      uint32_t page_num = pdfium::checked_cast<uint32_t>(atoi(args[0].c_str()));
+      // SAFETY: ByteStrings are always NUL-terminated.
+      uint32_t page_num =
+          pdfium::checked_cast<uint32_t>(UNSAFE_BUFFERS(atoi(args[0].c_str())));
       if (page_num == 0 || page_num > nCount)
         return std::vector<uint32_t>();
       results.push_back(page_num - 1);
     } else if (args.size() == 2) {
+      // SAFETY: ByteStrings are always NUL-terminated.
       uint32_t first_num =
-          pdfium::checked_cast<uint32_t>(atoi(args[0].c_str()));
+          pdfium::checked_cast<uint32_t>(UNSAFE_BUFFERS(atoi(args[0].c_str())));
       if (first_num == 0)
         return std::vector<uint32_t>();
-      uint32_t last_num = pdfium::checked_cast<uint32_t>(atoi(args[1].c_str()));
+      // SAFETY: ByteStrings are always NUL-terminated.
+      uint32_t last_num =
+          pdfium::checked_cast<uint32_t>(UNSAFE_BUFFERS(atoi(args[1].c_str())));
       if (last_num == 0 || first_num > last_num || last_num > nCount)
         return std::vector<uint32_t>();
       for (uint32_t i = first_num; i <= last_num; ++i)
diff --git a/fpdfsdk/fpdf_attachment_embeddertest.cpp b/fpdfsdk/fpdf_attachment_embeddertest.cpp
index 66799ef..5f969a3 100644
--- a/fpdfsdk/fpdf_attachment_embeddertest.cpp
+++ b/fpdfsdk/fpdf_attachment_embeddertest.cpp
@@ -150,7 +150,7 @@
   // Set the new attachment's file.
   static constexpr char kContents1[] = "Hello!";
   EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents1,
-                                     strlen(kContents1)));
+                                     UNSAFE_TODO(strlen(kContents1))));
   EXPECT_EQ(3, FPDFDoc_GetAttachmentCount(document()));
 
   // Verify the name of the new attachment (i.e. the first attachment).
@@ -177,7 +177,7 @@
   ASSERT_TRUE(attachment);
   static constexpr char kContents2[] = "World!";
   EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents2,
-                                     strlen(kContents2)));
+                                     UNSAFE_TODO(strlen(kContents2))));
   EXPECT_EQ(4, FPDFDoc_GetAttachmentCount(document()));
 
   // Verify the name of the new attachment (i.e. the fourth attachment).
@@ -211,7 +211,7 @@
   ASSERT_TRUE(attachment);
   static constexpr char kContents[] = "Hello World!";
   EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents,
-                                     strlen(kContents)));
+                                     UNSAFE_TODO(strlen(kContents))));
 
   // Set the date to be an arbitrary value.
   static constexpr wchar_t kDateW[] = L"D:20170720161527-04'00'";
@@ -290,7 +290,7 @@
   // Set the new attachment's file.
   static constexpr char kContents1[] = "Hello!";
   EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents1,
-                                     strlen(kContents1)));
+                                     UNSAFE_TODO(strlen(kContents1))));
   EXPECT_EQ(1, FPDFDoc_GetAttachmentCount(document()));
 
   // Verify the name of the new attachment (i.e. the first attachment).
@@ -317,7 +317,7 @@
   ASSERT_TRUE(attachment);
   static constexpr char kContents2[] = "World!";
   EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents2,
-                                     strlen(kContents2)));
+                                     UNSAFE_TODO(strlen(kContents2))));
   EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
 
   // Verify the name of the new attachment (i.e. the second attachment).
diff --git a/fpdfsdk/fpdf_edittext.cpp b/fpdfsdk/fpdf_edittext.cpp
index 23c8c3d..63ed5c2 100644
--- a/fpdfsdk/fpdf_edittext.cpp
+++ b/fpdfsdk/fpdf_edittext.cpp
@@ -703,8 +703,11 @@
                           uint32_t cid_to_gid_map_data_size) {
   CPDF_Document* doc = CPDFDocumentFromFPDFDocument(document);
   if (!doc || !font_data || font_data_size == 0 || !to_unicode_cmap ||
-      strlen(to_unicode_cmap) == 0 || !cid_to_gid_map_data ||
-      cid_to_gid_map_data_size == 0) {
+      !cid_to_gid_map_data || cid_to_gid_map_data_size == 0) {
+    return nullptr;
+  }
+  // SAFETY: required from caller.
+  if (UNSAFE_BUFFERS(strlen(to_unicode_cmap)) == 0) {
     return nullptr;
   }
   // SAFETY: required from caller.
diff --git a/fpdfsdk/fpdf_javascript_embeddertest.cpp b/fpdfsdk/fpdf_javascript_embeddertest.cpp
index a366bf2..1b94a40 100644
--- a/fpdfsdk/fpdf_javascript_embeddertest.cpp
+++ b/fpdfsdk/fpdf_javascript_embeddertest.cpp
@@ -85,7 +85,7 @@
   UNSAFE_TODO(FXSYS_memcpy(buf.data(), "abcdefgh", 8));
   EXPECT_EQ(kExpectedLength, FPDFJavaScriptAction_GetName(js.get(), buf.data(),
                                                           kExpectedLength - 1));
-  EXPECT_EQ(0, memcmp(buf.data(), "abcdefgh", 8));
+  EXPECT_EQ(0, UNSAFE_TODO(memcmp(buf.data(), "abcdefgh", 8)));
 
   EXPECT_EQ(kExpectedLength, FPDFJavaScriptAction_GetName(js.get(), buf.data(),
                                                           kExpectedLength));
@@ -115,7 +115,7 @@
   UNSAFE_TODO(FXSYS_memcpy(buf.data(), "abcdefgh", 8));
   EXPECT_EQ(kExpectedLength, FPDFJavaScriptAction_GetScript(
                                  js.get(), buf.data(), kExpectedLength - 1));
-  EXPECT_EQ(0, memcmp(buf.data(), "abcdefgh", 8));
+  EXPECT_EQ(0, UNSAFE_TODO(memcmp(buf.data(), "abcdefgh", 8)));
 
   static const wchar_t kExpectedScript[] =
       L"function ping() {\n  app.alert(\"ping\");\n}\n"
diff --git a/fpdfsdk/fpdf_signature_embeddertest.cpp b/fpdfsdk/fpdf_signature_embeddertest.cpp
index 1d36fa5..70f275e 100644
--- a/fpdfsdk/fpdf_signature_embeddertest.cpp
+++ b/fpdfsdk/fpdf_signature_embeddertest.cpp
@@ -54,7 +54,7 @@
   std::vector<char> contents(size);
   ASSERT_EQ(size,
             FPDFSignatureObj_GetContents(signature, contents.data(), size));
-  ASSERT_EQ(0, memcmp(kExpectedContents, contents.data(), size));
+  ASSERT_EQ(0, UNSAFE_TODO(memcmp(kExpectedContents, contents.data(), size)));
 
   // FPDFSignatureObj_GetContents() negative testing.
   ASSERT_EQ(0U, FPDFSignatureObj_GetContents(nullptr, nullptr, 0));
@@ -108,7 +108,8 @@
   std::vector<char> sub_filter(size);
   ASSERT_EQ(size,
             FPDFSignatureObj_GetSubFilter(signature, sub_filter.data(), size));
-  ASSERT_EQ(0, memcmp(kExpectedSubFilter, sub_filter.data(), size));
+  ASSERT_EQ(0,
+            UNSAFE_TODO(memcmp(kExpectedSubFilter, sub_filter.data(), size)));
 
   // FPDFSignatureObj_GetSubFilter() negative testing.
   ASSERT_EQ(0U, FPDFSignatureObj_GetSubFilter(nullptr, nullptr, 0));
@@ -174,7 +175,7 @@
   std::vector<char> time_buffer(size);
   ASSERT_EQ(size,
             FPDFSignatureObj_GetTime(signature, time_buffer.data(), size));
-  ASSERT_EQ(0, memcmp(kExpectedTime, time_buffer.data(), size));
+  ASSERT_EQ(0, UNSAFE_TODO(memcmp(kExpectedTime, time_buffer.data(), size)));
 
   // FPDFSignatureObj_GetTime() negative testing.
   ASSERT_EQ(0U, FPDFSignatureObj_GetTime(nullptr, nullptr, 0));
diff --git a/fpdfsdk/fpdf_sysfontinfo.cpp b/fpdfsdk/fpdf_sysfontinfo.cpp
index 6aca358..1cafcf9 100644
--- a/fpdfsdk/fpdf_sysfontinfo.cpp
+++ b/fpdfsdk/fpdf_sysfontinfo.cpp
@@ -240,9 +240,10 @@
 
   const unsigned long copy_length =
       pdfium::checked_cast<unsigned long>(name.GetLength() + 1);
-  if (copy_length <= buf_size)
-    strncpy(buffer, name.c_str(), copy_length * sizeof(ByteString::CharType));
-
+  if (copy_length <= buf_size) {
+    UNSAFE_TODO(strncpy(buffer, name.c_str(),
+                        copy_length * sizeof(ByteString::CharType)));
+  }
   return copy_length;
 }
 
diff --git a/fpdfsdk/fpdf_text_embeddertest.cpp b/fpdfsdk/fpdf_text_embeddertest.cpp
index 1d626f4..815dd91 100644
--- a/fpdfsdk/fpdf_text_embeddertest.cpp
+++ b/fpdfsdk/fpdf_text_embeddertest.cpp
@@ -1313,7 +1313,7 @@
   }
 
   // Now test larger start values.
-  const int kExpectedLength = strlen(kHelloGoodbyeText);
+  const int kExpectedLength = UNSAFE_TODO(strlen(kHelloGoodbyeText));
   for (int start = kGoodbyeWorldStart + 1; start < kExpectedLength; ++start) {
     EXPECT_EQ(1, FPDFText_CountRects(textpage.get(), start, -1));
     EXPECT_EQ(0, FPDFText_CountRects(textpage.get(), start, 0));
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index 4128b6c..ac960e8 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -1236,12 +1236,13 @@
 FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Set(FPDF_BSTR* bstr,
                                                     const char* cstr,
                                                     int length) {
-  if (!bstr || !cstr)
+  if (!bstr || !cstr) {
     return -1;
-
-  if (length == -1)
-    length = pdfium::checked_cast<int>(strlen(cstr));
-
+  }
+  if (length == -1) {
+    // SAFETY: required from caller.
+    length = pdfium::checked_cast<int>(UNSAFE_BUFFERS(strlen(cstr)));
+  }
   if (length == 0) {
     FPDF_BStr_Clear(bstr);
     return 0;
diff --git a/fpdfsdk/fpdf_view_embeddertest.cpp b/fpdfsdk/fpdf_view_embeddertest.cpp
index bd67326..8c42582 100644
--- a/fpdfsdk/fpdf_view_embeddertest.cpp
+++ b/fpdfsdk/fpdf_view_embeddertest.cpp
@@ -684,7 +684,7 @@
 
   // Make sure |buf| does not get written into when it appears to be too small.
   // NOLINTNEXTLINE(runtime/printf)
-  strcpy(buf, "ABCD");
+  UNSAFE_TODO(strcpy(buf, "ABCD"));
   EXPECT_EQ(4U, FPDF_VIEWERREF_GetName(document(), "Foo", buf, 1));
   EXPECT_STREQ("ABCD", buf);
 
@@ -1288,9 +1288,9 @@
 
   for (const auto& testcase : kTestCases) {
     char name_buffer[20] = {};
-    ASSERT_EQ(strlen(testcase.name) + 1,
+    ASSERT_EQ(UNSAFE_TODO(strlen(testcase.name)) + 1,
               FPDF_GetXFAPacketName(document(), testcase.index, nullptr, 0));
-    EXPECT_EQ(strlen(testcase.name) + 1,
+    EXPECT_EQ(UNSAFE_TODO(strlen(testcase.name)) + 1,
               FPDF_GetXFAPacketName(document(), testcase.index, name_buffer,
                                     sizeof(name_buffer)));
     EXPECT_STREQ(testcase.name, name_buffer);
diff --git a/fxbarcode/oned/BC_OnedCodaBarWriter_unittest.cpp b/fxbarcode/oned/BC_OnedCodaBarWriter_unittest.cpp
index 57d4830..e767935 100644
--- a/fxbarcode/oned/BC_OnedCodaBarWriter_unittest.cpp
+++ b/fxbarcode/oned/BC_OnedCodaBarWriter_unittest.cpp
@@ -19,8 +19,8 @@
       "# ##  #  # "  // A Start
       "#  #  # ##";  // B End
   DataVector<uint8_t> encoded = writer.Encode("");
-  ASSERT_EQ(strlen(kExpected1), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected1); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected1)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected1)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i])) << i;
   }
   static const char kExpected2[] =
@@ -30,8 +30,8 @@
       "##  # # # "   // 3
       "#  #  # ##";  // B End
   encoded = writer.Encode("123");
-  ASSERT_EQ(strlen(kExpected2), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected2); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected2)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected2)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i])) << i;
   }
   static const char kExpected3[] =
@@ -44,8 +44,8 @@
       "# ## ## ## "  // +
       "#  #  # ##";  // B End
   encoded = writer.Encode("-$./:+");
-  ASSERT_EQ(strlen(kExpected3), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected3); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected3)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected3)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected3[i] != ' ', !!encoded[i])) << i;
   }
   static const char kExpected4[] =
@@ -69,8 +69,8 @@
       "# # ##  # "   // 1
       "#  #  # ##";  // B End
   encoded = writer.Encode("456.987987987/001");
-  ASSERT_EQ(strlen(kExpected4), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected4); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected4)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected4)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected4[i] != ' ', !!encoded[i])) << i;
   }
 }
@@ -114,8 +114,8 @@
       "#  # ## # "   // 7
       "# #  #  ##";  // * (same as C) End
   DataVector<uint8_t> encoded = writer.Encode("987");
-  ASSERT_EQ(strlen(kExpected), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected[i] != ' ', !!encoded[i])) << i;
   }
 }
diff --git a/fxbarcode/oned/BC_OnedCode39Writer_unittest.cpp b/fxbarcode/oned/BC_OnedCode39Writer_unittest.cpp
index 3c0aa80..65acb76 100644
--- a/fxbarcode/oned/BC_OnedCode39Writer_unittest.cpp
+++ b/fxbarcode/oned/BC_OnedCode39Writer_unittest.cpp
@@ -38,8 +38,8 @@
       "### ### # #   # "  // M
       "#   # ### ### #";  // * End
   DataVector<uint8_t> encoded = writer.Encode("PDFIUM");
-  ASSERT_EQ(strlen(kExpected1), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected1); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected1)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected1)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i])) << i;
   }
   writer.SetWideNarrowRatio(2);
@@ -54,8 +54,8 @@
       "## ## # #  # "  // M
       "#  # ## ## #";  // * End
   encoded = writer.Encode("PDFIUM");
-  ASSERT_EQ(strlen(kExpected2), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected2); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected2)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected2)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i])) << i;
   }
 }
@@ -67,8 +67,8 @@
       "#   # ### ### # "  // * Start
       "#   # ### ### #";  // * End
   DataVector<uint8_t> encoded = writer.Encode("");
-  ASSERT_EQ(strlen(kExpected1), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected1); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected1)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected1)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i])) << i;
   }
 
@@ -79,8 +79,8 @@
       "### ###   # # # "  // 3
       "#   # ### ### #";  // * End
   encoded = writer.Encode("123");
-  ASSERT_EQ(strlen(kExpected2), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected2); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected2)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected2)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i])) << i;
   }
 
@@ -94,8 +94,8 @@
       "### ### # #   # "  // M
       "#   # ### ### #";  // * End
   encoded = writer.Encode("PDFIUM");
-  ASSERT_EQ(strlen(kExpected3), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected3); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected3)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected3)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected3[i] != ' ', !!encoded[i])) << i;
   }
 
@@ -112,8 +112,8 @@
       "#   ### ### # # "  // Z
       "#   # ### ### #";  // * End
   encoded = writer.Encode("A -$%./+Z");
-  ASSERT_EQ(strlen(kExpected4), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected4); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected4)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected4)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected4[i] != ' ', !!encoded[i])) << i;
   }
 }
@@ -130,9 +130,10 @@
       "# ###   ### # # "  // 6 (6 = (1 + 2 + 3) % 43)
       "#   # ### ### #";  // * End
   DataVector<uint8_t> encoded = writer.Encode("123");
-  ASSERT_EQ(strlen(kExpected1), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected1); i++)
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected1)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected1)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i])) << i;
+  }
 
   static const char kExpected2[] =
       "#   # ### ### # "  // * Start
@@ -145,8 +146,8 @@
       "###   # # ### # "  // . (37 = (25 + 13 + 15 + 18 + 30 + 22) % 43)
       "#   # ### ### #";  // * End
   encoded = writer.Encode("PDFIUM");
-  ASSERT_EQ(strlen(kExpected2), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected2); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected2)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected2)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i])) << i;
   }
 }
diff --git a/fxbarcode/oned/BC_OnedEAN13Writer_unittest.cpp b/fxbarcode/oned/BC_OnedEAN13Writer_unittest.cpp
index 6671fe2..9636b07 100644
--- a/fxbarcode/oned/BC_OnedEAN13Writer_unittest.cpp
+++ b/fxbarcode/oned/BC_OnedEAN13Writer_unittest.cpp
@@ -41,7 +41,7 @@
       "#  #   "  // 8 R
       "# #";     // End
   DataVector<uint8_t> encoded = writer.Encode("1234567890128");
-  for (size_t i = 0; i < strlen(kExpected1); i++) {
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected1)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i])) << i;
   }
   static const char kExpected2[] =
@@ -62,8 +62,8 @@
       "###  # "  // 0 R
       "# #";     // End
   encoded = writer.Encode("7776665554440");
-  ASSERT_EQ(strlen(kExpected2), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected2); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected2)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected2)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i])) << i;
   }
 }
diff --git a/fxbarcode/oned/BC_OnedEAN8Writer_unittest.cpp b/fxbarcode/oned/BC_OnedEAN8Writer_unittest.cpp
index 12fa994..612779f 100644
--- a/fxbarcode/oned/BC_OnedEAN8Writer_unittest.cpp
+++ b/fxbarcode/oned/BC_OnedEAN8Writer_unittest.cpp
@@ -36,8 +36,8 @@
       "###  # "  // 0 R
       "# #";     // End
   DataVector<uint8_t> encoded = writer.Encode("12345670");
-  ASSERT_EQ(strlen(kExpected1), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected1); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected1)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected1)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i])) << i;
   }
   static const char kExpected2[] =
@@ -53,9 +53,10 @@
       "# ###  "  // 4 R
       "# #";     // End
   encoded = writer.Encode("99441104");
-  ASSERT_EQ(strlen(kExpected2), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected2); i++)
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected2)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected2)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i])) << i;
+  }
 }
 
 TEST(OnedEAN8WriterTest, Checksum) {
diff --git a/fxbarcode/oned/BC_OnedUPCAWriter_unittest.cpp b/fxbarcode/oned/BC_OnedUPCAWriter_unittest.cpp
index e818d7c..cb56389 100644
--- a/fxbarcode/oned/BC_OnedUPCAWriter_unittest.cpp
+++ b/fxbarcode/oned/BC_OnedUPCAWriter_unittest.cpp
@@ -40,8 +40,8 @@
       "## ##  "  // 2 R
       "# #";     // End
   DataVector<uint8_t> encoded = writer.Encode("123456789012");
-  ASSERT_EQ(strlen(kExpected1), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected1); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected1)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected1)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i])) << i;
   }
 
@@ -62,8 +62,8 @@
       "# ###  "  // 4 R
       "###  # "  // 0 R
       "# #";     // End
-  ASSERT_EQ(strlen(kExpected2), encoded.size());
-  for (size_t i = 0; i < strlen(kExpected2); i++) {
+  ASSERT_EQ(UNSAFE_TODO(strlen(kExpected2)), encoded.size());
+  for (size_t i = 0; i < UNSAFE_TODO(strlen(kExpected2)); i++) {
     UNSAFE_TODO(EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i])) << i;
   }
 }
diff --git a/fxjs/cjs_publicmethods.cpp b/fxjs/cjs_publicmethods.cpp
index f935264..7bb7a86 100644
--- a/fxjs/cjs_publicmethods.cpp
+++ b/fxjs/cjs_publicmethods.cpp
@@ -616,7 +616,9 @@
 
   // Processing decimal places
   NormalizeDecimalMark(&strValue);
-  double dValue = atof(strValue.c_str());
+
+  // SAFETY: ByteStrings are always NUL-terminated.
+  double dValue = UNSAFE_BUFFERS(atof(strValue.c_str()));
   if (iDec > 0)
     dValue += kDoubleCorrect;
 
@@ -822,7 +824,8 @@
     strValue = "0";
 
   // for processing decimal places
-  double dValue = atof(strValue.c_str());
+  // SAFETY: ByteStrings are always NUL-terminated.
+  double dValue = UNSAFE_BUFFERS(atof(strValue.c_str()));
   dValue *= 100;
 
   size_t szNewSize;
@@ -842,8 +845,8 @@
 
     // Write into |strValue|.
     pdfium::span<char> span = strValue.GetBuffer(szBufferSize);
-    FXSYS_snprintf(span.data(), szBufferSize, format, dValue);
-    szNewSize = strlen(span.data());
+    UNSAFE_TODO(FXSYS_snprintf(span.data(), szBufferSize, format, dValue));
+    szNewSize = UNSAFE_TODO(strlen(span.data()));
   }
   strValue.ReleaseBuffer(szNewSize);
 
@@ -1392,7 +1395,8 @@
   if (pEvent->Value().IsEmpty())
     return CJS_Result::Success();
 
-  double dEventValue = atof(pEvent->Value().ToUTF8().c_str());
+  // SAFETY: ByteStrings are always NUL-terminated.
+  double dEventValue = UNSAFE_BUFFERS(atof(pEvent->Value().ToUTF8().c_str()));
   bool bGreaterThan = pRuntime->ToBoolean(params[0]);
   double dGreaterThan = pRuntime->ToDouble(params[1]);
   bool bLessThan = pRuntime->ToBoolean(params[2]);
diff --git a/fxjs/cjs_util.cpp b/fxjs/cjs_util.cpp
index e3c22c2..ce580b5 100644
--- a/fxjs/cjs_util.cpp
+++ b/fxjs/cjs_util.cpp
@@ -225,7 +225,7 @@
       if (nFound == std::wstring::npos) {
         break;
       }
-      cFormat.replace(nFound, wcslen(conversion.lpszJSMark),
+      cFormat.replace(nFound, UNSAFE_TODO(wcslen(conversion.lpszJSMark)),
                       conversion.lpszCppMark);
     }
   }
diff --git a/fxjs/js_define.h b/fxjs/js_define.h
index 58163ff..1175dcc 100644
--- a/fxjs/js_define.h
+++ b/fxjs/js_define.h
@@ -131,7 +131,8 @@
   for (unsigned int i = 0; i < (unsigned int)info.Length(); i++)
     parameters.push_back(info[i]);
 
-  CJS_Result result = (pObj.get()->*M)(pRuntime, parameters);
+  // TODO(tsepez): why does the compiler think this is sometimes unsafe?
+  CJS_Result result = UNSAFE_TODO((pObj.get()->*M)(pRuntime, parameters));
   if (result.HasError()) {
     pRuntime->Error(JSFormatErrorString(class_name_string, method_name_string,
                                         result.Error()));
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp
index 27db406..796768b 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -549,7 +549,8 @@
 
 bool HTMLSTR2Code(const WideString& pData, uint32_t* iCode) {
   auto cmpFunc = [](const XFA_FMHtmlReserveCode& iter, ByteStringView val) {
-    return strcmp(val.unterminated_c_str(), iter.m_htmlReserve) > 0;
+    return UNSAFE_TODO(strcmp(val.unterminated_c_str(), iter.m_htmlReserve)) >
+           0;
   };
   if (!pData.IsASCII())
     return false;
@@ -558,7 +559,7 @@
       std::begin(kReservesForDecode), std::end(kReservesForDecode),
       temp.AsStringView(), cmpFunc);
   if (result != std::end(kReservesForDecode) &&
-      !strcmp(temp.c_str(), result->m_htmlReserve)) {
+      !UNSAFE_TODO(strcmp(temp.c_str(), result->m_htmlReserve))) {
     *iCode = result->m_uCode;
     return true;
   }
@@ -1098,7 +1099,8 @@
 
   if (fxv8::IsString(extracted)) {
     ByteString bsValue = fxv8::ReentrantToByteStringHelper(pIsolate, extracted);
-    return strtof(bsValue.c_str(), nullptr);
+    // SAFETY: ByteStrings are always NUL-terminated.
+    return UNSAFE_BUFFERS(strtof(bsValue.c_str(), nullptr));
   }
 
   return fxv8::ReentrantToFloatHelper(pIsolate, extracted);
@@ -1117,7 +1119,8 @@
 
   if (fxv8::IsString(extracted)) {
     ByteString bsValue = fxv8::ReentrantToByteStringHelper(pIsolate, extracted);
-    return strtod(bsValue.c_str(), nullptr);
+    // SAFETY: ByteStrings are always NUL_terminated.
+    return UNSAFE_BUFFERS(strtod(bsValue.c_str(), nullptr));
   }
 
   return fxv8::ReentrantToDoubleHelper(pIsolate, extracted);
diff --git a/xfa/fgas/crt/cfgas_stringformatter.cpp b/xfa/fgas/crt/cfgas_stringformatter.cpp
index 38eae09..fd58d99 100644
--- a/xfa/fgas/crt/cfgas_stringformatter.cpp
+++ b/xfa/fgas/crt/cfgas_stringformatter.cpp
@@ -217,7 +217,8 @@
       continue;
     }
     if (ccf + spDotSymbol.size() <= spNum.size() &&
-        wcsncmp(&spNum[ccf], spDotSymbol.data(), spDotSymbol.size()) == 0) {
+        UNSAFE_TODO(wcsncmp(&spNum[ccf], spDotSymbol.data(),
+                            spDotSymbol.size())) == 0) {
       *iDotIndex = ccf;
       return true;
     }
diff --git a/xfa/fxfa/parser/cxfa_localevalue.cpp b/xfa/fxfa/parser/cxfa_localevalue.cpp
index c938f7a..92cff00 100644
--- a/xfa/fxfa/parser/cxfa_localevalue.cpp
+++ b/xfa/fxfa/parser/cxfa_localevalue.cpp
@@ -224,7 +224,8 @@
     return 0;
   }
 
-  return wcstod(m_wsValue.c_str(), nullptr);
+  // SAFETY: WideStrings are always terminated.
+  return UNSAFE_BUFFERS(wcstod(m_wsValue.c_str(), nullptr));
 }
 
 CFX_DateTime CXFA_LocaleValue::GetDate() const {