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 {