summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2018-03-15 17:00:16 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2018-03-15 17:00:16 +0000
commita4ff69b3554b569a04e4327ca22b9dad262d7141 (patch)
treef548e640ad238d6f0a7cd3f677f08e77c5cb92e3
parent46abf7e01c369a92731ba3a9c01532ebbc7c77e5 (diff)
parent594e33f93a3a35cf2cbfda67edc0d80ee1423327 (diff)
downloadminikin-oreo-m2-release.tar.gz
Change-Id: Ifd3d40f768331bbd9402e2149de733b0a1f5ced6
-rw-r--r--libs/minikin/CmapCoverage.cpp24
-rw-r--r--tests/unittest/CmapCoverageTest.cpp48
2 files changed, 66 insertions, 6 deletions
diff --git a/libs/minikin/CmapCoverage.cpp b/libs/minikin/CmapCoverage.cpp
index c6318f5..78e7b0d 100644
--- a/libs/minikin/CmapCoverage.cpp
+++ b/libs/minikin/CmapCoverage.cpp
@@ -319,8 +319,12 @@ static bool getVSCoverage(std::vector<uint32_t>* out_ranges, const uint8_t* data
if (nonDefaultUVSTableRemaining < kHeaderSize) {
return false;
}
- const uint32_t numRecords = readU32(nonDefaultUVSTable, 0);
- if (numRecords * kUVSMappingRecordSize + kHeaderSize > nonDefaultUVSTableRemaining) {
+ const uint64_t numRecords = readU32(nonDefaultUVSTable, 0);
+ const uint64_t sizeToRead = numRecords * kUVSMappingRecordSize + kHeaderSize;
+ if (sizeToRead > nonDefaultUVSTableRemaining) {
+ if (sizeToRead > UINT_MAX) {
+ android_errorWriteLog(0x534e4554, "70808908");
+ }
return false;
}
for (uint32_t i = 0; i < numRecords; ++i) {
@@ -347,8 +351,12 @@ static bool getVSCoverage(std::vector<uint32_t>* out_ranges, const uint8_t* data
if (defaultUVSTableRemaining < kHeaderSize) {
return false;
}
- const uint32_t numRecords = readU32(defaultUVSTable, 0);
- if (numRecords * kUnicodeRangeRecordSize + kHeaderSize > defaultUVSTableRemaining) {
+ const uint64_t numRecords = readU32(defaultUVSTable, 0);
+ const uint64_t sizeToRead = numRecords * kUnicodeRangeRecordSize + kHeaderSize;
+ if (sizeToRead > defaultUVSTableRemaining) {
+ if (sizeToRead > UINT_MAX) {
+ android_errorWriteLog(0x534e4554, "70808908");
+ }
return false;
}
@@ -392,8 +400,12 @@ static void getCoverageFormat14(std::vector<std::unique_ptr<SparseBitSet>>* out,
return;
}
- uint32_t numRecords = readU32(data, kNumRecordOffset);
- if (numRecords == 0 || kHeaderSize + kRecordSize * numRecords > length) {
+ const uint64_t numRecords = readU32(data, kNumRecordOffset);
+ const uint64_t sizeToRead = kHeaderSize + kRecordSize * numRecords;
+ if (numRecords == 0 || sizeToRead > length) {
+ if (sizeToRead > UINT_MAX) {
+ android_errorWriteLog(0x534e4554, "70808908");
+ }
return;
}
diff --git a/tests/unittest/CmapCoverageTest.cpp b/tests/unittest/CmapCoverageTest.cpp
index fe2d7ba..590a363 100644
--- a/tests/unittest/CmapCoverageTest.cpp
+++ b/tests/unittest/CmapCoverageTest.cpp
@@ -988,6 +988,54 @@ TEST(CmapCoverageTest, TableSelection_brokenVSTable) {
SparseBitSet coverage = CmapCoverage::getCoverage(cmap.data(), cmap.size(), &vsTables);
ASSERT_TRUE(vsTables.empty());
}
+ {
+ // http://b/70808908
+ SCOPED_TRACE("OOB access due to integer overflow in non default UVS table");
+ std::vector<uint8_t> vsTable = buildCmapFormat14Table(
+ std::vector<VariationSelectorRecord>({{0xFE0F, {'a', 'a'}, {'b'}}}));
+ // 6 is the offset of the numRecords in the Cmap format14 subtable header.
+ writeU32(0x1745d174 /* 2^32 / kRecordSize(=11) */, vsTable.data(), 6);
+ CmapBuilder builder(2);
+ builder.appendTable(3, 1, cmap12Table);
+ builder.appendTable(VS_PLATFORM_ID, VS_ENCODING_ID, vsTable);
+ std::vector<uint8_t> cmap = builder.build();
+
+ std::vector<std::unique_ptr<SparseBitSet>> vsTables;
+ SparseBitSet coverage = CmapCoverage::getCoverage(cmap.data(), cmap.size(), &vsTables);
+ ASSERT_TRUE(vsTables.empty());
+ }
+ {
+ // http://b/70808908
+ SCOPED_TRACE("OOB access due to integer overflow in non default UVS table");
+ std::vector<uint8_t> vsTable = buildCmapFormat14Table(
+ std::vector<VariationSelectorRecord>({{0xFE0F, {'a', 'a'}, {'b'}}}));
+ // 29 is the offset of the numUVSMappings in the fist non defulat UVS table.
+ writeU32(0x33333333 /* 2^32 / kUVSMappingRecordSize(=5) */, vsTable.data(), 29);
+ CmapBuilder builder(2);
+ builder.appendTable(3, 1, cmap12Table);
+ builder.appendTable(VS_PLATFORM_ID, VS_ENCODING_ID, vsTable);
+ std::vector<uint8_t> cmap = builder.build();
+
+ std::vector<std::unique_ptr<SparseBitSet>> vsTables;
+ SparseBitSet coverage = CmapCoverage::getCoverage(cmap.data(), cmap.size(), &vsTables);
+ ASSERT_TRUE(vsTables.empty());
+ }
+ {
+ // http://b/70808908
+ SCOPED_TRACE("OOB access due to integer overflow in default UVS table");
+ std::vector<uint8_t> vsTable = buildCmapFormat14Table(
+ std::vector<VariationSelectorRecord>({{0xFE0F, {'a', 'a'}, {'b'}}}));
+ // 21 is the offset of the numUnicodeValueRanges in the fist defulat UVS table.
+ writeU32(0x40000000 /* 2^32 / kUnicodeRangeRecordSize(=4) */, vsTable.data(), 21);
+ CmapBuilder builder(2);
+ builder.appendTable(3, 1, cmap12Table);
+ builder.appendTable(VS_PLATFORM_ID, VS_ENCODING_ID, vsTable);
+ std::vector<uint8_t> cmap = builder.build();
+
+ std::vector<std::unique_ptr<SparseBitSet>> vsTables;
+ SparseBitSet coverage = CmapCoverage::getCoverage(cmap.data(), cmap.size(), &vsTables);
+ ASSERT_TRUE(vsTables.empty());
+ }
}
TEST(CmapCoverageTest, TableSelection_brokenVSTable_bestEffort) {