Fix timeout in pdf_cpdf_tounicodemap_fuzzer Iterating through a range of multimap to check for duplicate cid-unicode mappings can be too time consuming and cause timeout in CPDF_ToUnicodeMap::InsertIntoMultimap(). This CL changes `m_Multimap` into std::map<uint32_t, std::set<uint32_t>> so that no duplicate unicode can be inserted into the set by default and the insertion can be done more efficiently to avoid timeout. Bug: chromium:1347025 Change-Id: I54bdf4cc2d34f1dd0c0f18d82c9b3a7941833269 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/95791 Reviewed-by: Lei Zhang <thestig@chromium.org> Commit-Queue: Nigi <nigi@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_tounicodemap.cpp b/core/fpdfapi/font/cpdf_tounicodemap.cpp index 00714f1..349783c 100644 --- a/core/fpdfapi/font/cpdf_tounicodemap.cpp +++ b/core/fpdfapi/font/cpdf_tounicodemap.cpp
@@ -7,6 +7,7 @@ #include "core/fpdfapi/font/cpdf_tounicodemap.h" #include <map> +#include <set> #include <utility> #include "core/fpdfapi/font/cpdf_cid2unicodemap.h" @@ -54,7 +55,7 @@ m_pBaseMap->UnicodeFromCID(static_cast<uint16_t>(charcode))); } - uint32_t value = it->second; + uint32_t value = *it->second.begin(); wchar_t unicode = static_cast<wchar_t>(value & 0xffff); if (unicode != 0xffff) return WideString(unicode); @@ -65,12 +66,18 @@ uint32_t CPDF_ToUnicodeMap::ReverseLookup(wchar_t unicode) const { for (const auto& pair : m_Multimap) { - if (pair.second == static_cast<uint32_t>(unicode)) + if (pdfium::Contains(pair.second, static_cast<uint32_t>(unicode))) return pair.first; } return 0; } +size_t CPDF_ToUnicodeMap::GetUnicodeCountByCharcodeForTesting( + uint32_t charcode) const { + auto it = m_Multimap.find(charcode); + return it != m_Multimap.end() ? it->second.size() : 0u; +} + // static absl::optional<uint32_t> CPDF_ToUnicodeMap::StringToCode(ByteStringView str) { size_t len = str.GetLength(); @@ -228,18 +235,11 @@ } void CPDF_ToUnicodeMap::InsertIntoMultimap(uint32_t code, uint32_t destcode) { - if (!pdfium::Contains(m_Multimap, code)) { - m_Multimap.emplace(code, destcode); + auto it = m_Multimap.find(code); + if (it == m_Multimap.end()) { + m_Multimap.emplace(code, std::set<uint32_t>{destcode}); return; } - auto ret = m_Multimap.equal_range(code); - for (auto iter = ret.first; iter != ret.second; ++iter) { - if (iter->second == destcode) { - // Do not insert since a duplicate mapping is found. - return; - } - } - - m_Multimap.emplace(code, destcode); + it->second.emplace(destcode); }
diff --git a/core/fpdfapi/font/cpdf_tounicodemap.h b/core/fpdfapi/font/cpdf_tounicodemap.h index 61d0ac6..7935ede 100644 --- a/core/fpdfapi/font/cpdf_tounicodemap.h +++ b/core/fpdfapi/font/cpdf_tounicodemap.h
@@ -8,6 +8,7 @@ #define CORE_FPDFAPI_FONT_CPDF_TOUNICODEMAP_H_ #include <map> +#include <set> #include <vector> #include "core/fxcrt/fx_string.h" @@ -26,7 +27,7 @@ WideString Lookup(uint32_t charcode) const; uint32_t ReverseLookup(wchar_t unicode) const; - size_t GetMultimapSizeForTesting() const { return m_Multimap.size(); } + size_t GetUnicodeCountByCharcodeForTesting(uint32_t cid) const; private: friend class cpdf_tounicodemap_StringToCode_Test; @@ -45,7 +46,7 @@ // before. void InsertIntoMultimap(uint32_t code, uint32_t destcode); - std::multimap<uint32_t, uint32_t> m_Multimap; + std::map<uint32_t, std::set<uint32_t>> m_Multimap; UnownedPtr<const CPDF_CID2UnicodeMap> m_pBaseMap; std::vector<WideString> m_MultiCharVec; };
diff --git a/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp index 098983c..74eaa3b 100644 --- a/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp +++ b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp
@@ -90,7 +90,8 @@ CPDF_ToUnicodeMap map(stream.Get()); EXPECT_EQ(1u, map.ReverseLookup(0x0041)); EXPECT_EQ(2u, map.ReverseLookup(0x0042)); - EXPECT_EQ(2u, map.GetMultimapSizeForTesting()); + EXPECT_EQ(1u, map.GetUnicodeCountByCharcodeForTesting(1u)); + EXPECT_EQ(1u, map.GetUnicodeCountByCharcodeForTesting(2u)); } { // The same CID with different unicodes. @@ -101,7 +102,7 @@ CPDF_ToUnicodeMap map(stream.Get()); EXPECT_EQ(0u, map.ReverseLookup(0x0041)); EXPECT_EQ(0u, map.ReverseLookup(0x0042)); - EXPECT_EQ(2u, map.GetMultimapSizeForTesting()); + EXPECT_EQ(2u, map.GetUnicodeCountByCharcodeForTesting(0u)); } { // Duplicate mappings of CID 0 to unicode "A". There should be only 1 entry @@ -113,6 +114,6 @@ stream->SetData(pdfium::make_span(kInput3)); CPDF_ToUnicodeMap map(stream.Get()); EXPECT_EQ(0u, map.ReverseLookup(0x0041)); - EXPECT_EQ(1u, map.GetMultimapSizeForTesting()); + EXPECT_EQ(1u, map.GetUnicodeCountByCharcodeForTesting(0u)); } }