summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeigo Nonaka <nona@google.com>2018-03-21 14:36:13 -0700
committerSeigo Nonaka <nona@google.com>2018-03-21 15:08:05 -0700
commit048b45f69c2a6a43329fc8efd056666f427a62d4 (patch)
tree71257165a5e199fe30703305540494f23f91075a
parent43a52c5ee653e75ce3ccf2477a9dcdec6f8d7fa3 (diff)
downloadminikin-048b45f69c2a6a43329fc8efd056666f427a62d4.tar.gz
Revive support of duplicated entry in cmap format 4
Minikin rejects unordered (including duplicated) cmap entries for security reasons. (Issue 32178311). The duplicated entries are invalid for cmap format 12 or cmap format 14 but valid for cmap format 4. Bug: 76103006 Test: manual Test: minikin_test Test: atest CtsWidgetTestCases:EditTextTest CtsWidgetTestCases:TextViewFadingEdgeTest FrameworksCoreTests:TextViewFallbackLineSpacingTest FrameworksCoreTests:TextViewTest FrameworksCoreTests:TypefaceTest CtsGraphicsTestCases:TypefaceTest CtsWidgetTestCases:TextViewTest CtsTextTestCases FrameworksCoreTests:android.text CtsWidgetTestCases:TextViewPrecomputedTextTest Change-Id: I902a11a93d01ccb609662e86e5ae2f3897940fb4
-rw-r--r--libs/minikin/CmapCoverage.cpp22
-rw-r--r--tests/unittest/CmapCoverageTest.cpp25
2 files changed, 44 insertions, 3 deletions
diff --git a/libs/minikin/CmapCoverage.cpp b/libs/minikin/CmapCoverage.cpp
index c00cec7..f6143d3 100644
--- a/libs/minikin/CmapCoverage.cpp
+++ b/libs/minikin/CmapCoverage.cpp
@@ -61,6 +61,22 @@ static bool addRange(std::vector<uint32_t>& coverage, uint32_t start, uint32_t e
}
}
+// Returns true if the range is appended. Otherwise returns false as an error.
+static bool addRangeCmap4(std::vector<uint32_t>& coverage, uint32_t start, uint32_t end) {
+ if (!coverage.empty() && coverage.back() > end) {
+ // Reject unordered end code points.
+ return false;
+ }
+ if (coverage.empty() || coverage.back() < start) {
+ coverage.push_back(start);
+ coverage.push_back(end);
+ return true;
+ } else {
+ coverage.back() = end;
+ return true;
+ }
+}
+
// Returns Range from given ranges vector. Returns invalidRange if i is out of range.
static inline Range getRange(const std::vector<uint32_t>& r, size_t i) {
return i + 1 < r.size() ? Range({r[i], r[i + 1]}) : Range::invalidRange();
@@ -157,13 +173,13 @@ static bool getCoverageFormat4(std::vector<uint32_t>& coverage, const uint8_t* d
if (rangeOffset == 0) {
uint32_t delta = readU16(data, kHeaderSize + 2 * (2 * segCount + i));
if (((end + delta) & 0xffff) > end - start) {
- if (!addRange(coverage, start, end + 1)) {
+ if (!addRangeCmap4(coverage, start, end + 1)) {
return false;
}
} else {
for (uint32_t j = start; j < end + 1; j++) {
if (((j + delta) & 0xffff) != 0) {
- if (!addRange(coverage, j, j + 1)) {
+ if (!addRangeCmap4(coverage, j, j + 1)) {
return false;
}
}
@@ -179,7 +195,7 @@ static bool getCoverageFormat4(std::vector<uint32_t>& coverage, const uint8_t* d
}
uint32_t glyphId = readU16(data, actualRangeOffset);
if (glyphId != 0) {
- if (!addRange(coverage, j, j + 1)) {
+ if (!addRangeCmap4(coverage, j, j + 1)) {
return false;
}
}
diff --git a/tests/unittest/CmapCoverageTest.cpp b/tests/unittest/CmapCoverageTest.cpp
index febfc37..9dba583 100644
--- a/tests/unittest/CmapCoverageTest.cpp
+++ b/tests/unittest/CmapCoverageTest.cpp
@@ -490,6 +490,31 @@ TEST(CmapCoverageTest, brokenFormat4Table) {
EXPECT_EQ(0U, coverage.length());
EXPECT_TRUE(vsTables.empty());
}
+ {
+ SCOPED_TRACE("Reversed end code points");
+ std::vector<uint8_t> table =
+ buildCmapFormat4Table(std::vector<uint16_t>({'b', 'b', 'a', 'a'}));
+ CmapBuilder builder(1);
+ builder.appendTable(0, 0, table);
+ std::vector<uint8_t> cmap = builder.build();
+
+ SparseBitSet coverage = CmapCoverage::getCoverage(cmap.data(), cmap.size(), &vsTables);
+ EXPECT_EQ(0U, coverage.length());
+ EXPECT_TRUE(vsTables.empty());
+ }
+}
+
+TEST(CmapCoverageTest, duplicatedCmap4EntryTest) {
+ std::vector<std::unique_ptr<SparseBitSet>> vsTables;
+ std::vector<uint8_t> table = buildCmapFormat4Table(std::vector<uint16_t>({'a', 'b', 'b', 'b'}));
+ CmapBuilder builder(1);
+ builder.appendTable(0, 0, table);
+ std::vector<uint8_t> cmap = builder.build();
+
+ SparseBitSet coverage = CmapCoverage::getCoverage(cmap.data(), cmap.size(), &vsTables);
+ EXPECT_TRUE(coverage.get('a'));
+ EXPECT_TRUE(coverage.get('b'));
+ EXPECT_TRUE(vsTables.empty());
}
TEST(CmapCoverageTest, brokenFormat12Table) {