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));
}
}