diff options
author | Seigo Nonaka <nona@google.com> | 2018-03-21 14:36:13 -0700 |
---|---|---|
committer | Seigo Nonaka <nona@google.com> | 2018-03-21 15:08:05 -0700 |
commit | 048b45f69c2a6a43329fc8efd056666f427a62d4 (patch) | |
tree | 71257165a5e199fe30703305540494f23f91075a | |
parent | 43a52c5ee653e75ce3ccf2477a9dcdec6f8d7fa3 (diff) | |
download | minikin-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.cpp | 22 | ||||
-rw-r--r-- | tests/unittest/CmapCoverageTest.cpp | 25 |
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) { |