Limit the CID code values in CPDF_ToUnicodeMap
It is not perfectly clear in the Adobe CMap and CIDFont Files
Specification, but all the examples and some auxiliary docs indicate
that the CID code values are never above 65535. Therefore, check for
that in CPDF_ToUnicodeMap, and stop worrying that code ranges can have
integer overflows.
Also check for invalid ranges where the low value is higher than the
high value. Adjust results for existing integer overflow cases. Expand
testing to cover new checks.
Bug: 41489089
Change-Id: I4c1e0f1a20ed239c925c75fa6f98863c46f07b7a
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/126030
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fpdfapi/font/cpdf_tounicodemap.cpp b/core/fpdfapi/font/cpdf_tounicodemap.cpp
index 058e8e1..7cbf881 100644
--- a/core/fpdfapi/font/cpdf_tounicodemap.cpp
+++ b/core/fpdfapi/font/cpdf_tounicodemap.cpp
@@ -6,7 +6,6 @@
#include "core/fpdfapi/font/cpdf_tounicodemap.h"
-#include <limits>
#include <set>
#include <utility>
@@ -21,6 +20,8 @@
namespace {
+constexpr uint32_t kCidLimit = 0xffff;
+
WideString StringDataAdd(WideString str) {
WideString ret;
wchar_t value = 1;
@@ -176,8 +177,9 @@
return;
std::optional<uint32_t> code = StringToCode(word);
- if (!code.has_value())
+ if (!code.has_value() || code.value() > kCidLimit) {
return;
+ }
SetCode(code.value(), StringToWideString(pParser->GetWord()));
}
@@ -200,14 +202,14 @@
uint32_t lowcode = lowcode_opt.value();
uint32_t highcode = (lowcode & 0xffffff00) | (highcode_opt.value() & 0xff);
+ if (lowcode > kCidLimit || highcode > kCidLimit || lowcode > highcode) {
+ return;
+ }
ByteStringView start = pParser->GetWord();
if (start == "[") {
for (uint32_t code = lowcode; code <= highcode; ++code) {
SetCode(code, StringToWideString(pParser->GetWord()));
- if (code == std::numeric_limits<uint32_t>::max()) {
- break;
- }
}
pParser->GetWord();
continue;
@@ -222,9 +224,6 @@
uint32_t value = value_or_error.value();
for (uint32_t code = lowcode; code <= highcode; ++code) {
InsertIntoMultimap(code, value++);
- if (code == std::numeric_limits<uint32_t>::max()) {
- break;
- }
}
} else {
for (uint32_t code = lowcode; code <= highcode; ++code) {
@@ -233,9 +232,6 @@
InsertIntoMultimap(code, GetMultiCharIndexIndicator());
m_MultiCharVec.push_back(retcode);
destcode = std::move(retcode);
- if (code == std::numeric_limits<uint32_t>::max()) {
- break;
- }
}
}
}
diff --git a/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp
index eb05a7a..cdd6ee8 100644
--- a/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp
+++ b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp
@@ -59,29 +59,54 @@
EXPECT_EQ(res, CPDF_ToUnicodeMap::StringToWideString("<c2abFaAb12>"));
}
-TEST(CPDFToUnicodeMapTest, HandleBeginBFRangeAvoidIntegerOverflow) {
- // Make sure there won't be infinite loops due to integer overflows in
- // HandleBeginBFRange().
+TEST(CPDFToUnicodeMapTest, HandleBeginBFRangeRejectsInvalidCidValues) {
{
static constexpr uint8_t kInput1[] =
"beginbfrange<FFFFFFFF><FFFFFFFF>[<0041>]endbfrange";
auto stream = pdfium::MakeRetain<CPDF_Stream>(kInput1);
CPDF_ToUnicodeMap map(stream);
- EXPECT_EQ(L"A", map.Lookup(0xffffffff));
+ EXPECT_EQ(L"", map.Lookup(0xffffffff));
}
{
static constexpr uint8_t kInput2[] =
"beginbfrange<FFFFFFFF><FFFFFFFF><0042>endbfrange";
auto stream = pdfium::MakeRetain<CPDF_Stream>(kInput2);
CPDF_ToUnicodeMap map(stream);
- EXPECT_EQ(L"B", map.Lookup(0xffffffff));
+ EXPECT_EQ(L"", map.Lookup(0xffffffff));
}
{
static constexpr uint8_t kInput3[] =
"beginbfrange<FFFFFFFF><FFFFFFFF><00410042>endbfrange";
auto stream = pdfium::MakeRetain<CPDF_Stream>(kInput3);
CPDF_ToUnicodeMap map(stream);
- EXPECT_EQ(L"AB", map.Lookup(0xffffffff));
+ EXPECT_EQ(L"", map.Lookup(0xffffffff));
+ }
+ {
+ static constexpr uint8_t kInput4[] =
+ "beginbfrange<0001><10000>[<0041>]endbfrange";
+ auto stream = pdfium::MakeRetain<CPDF_Stream>(kInput4);
+ CPDF_ToUnicodeMap map(stream);
+ EXPECT_EQ(L"", map.Lookup(0xffffffff));
+ EXPECT_EQ(L"", map.Lookup(0x0001));
+ EXPECT_EQ(L"", map.Lookup(0xffff));
+ EXPECT_EQ(L"", map.Lookup(0x10000));
+ }
+ {
+ static constexpr uint8_t kInput5[] =
+ "beginbfrange<10000><10001>[<0041>]endbfrange";
+ auto stream = pdfium::MakeRetain<CPDF_Stream>(kInput5);
+ CPDF_ToUnicodeMap map(stream);
+ EXPECT_EQ(L"", map.Lookup(0x10000));
+ EXPECT_EQ(L"", map.Lookup(0x10001));
+ }
+ {
+ static constexpr uint8_t kInput6[] =
+ "beginbfrange<0006><0004>[<0041>]endbfrange";
+ auto stream = pdfium::MakeRetain<CPDF_Stream>(kInput6);
+ CPDF_ToUnicodeMap map(stream);
+ EXPECT_EQ(L"", map.Lookup(0x0004));
+ EXPECT_EQ(L"", map.Lookup(0x0005));
+ EXPECT_EQ(L"", map.Lookup(0x0006));
}
}