Fixing 2 typo bugs
This CL fixes two typo bugs reported at Chromium bug tracker:
- [OTS] font sanitizer incorrectly drops GDEF table in LinLibertine_Re-4.7.5.ttf
- [OTS] error in 'cmap' parser can crash the process using OTS
And, this CL modifies several boundary calculations to avoid overflow.
This CL also updates BLACKLIST.txt; some fonts have wrong offset in MarkAttachClassDef field of GDEF header table.
R=yusukes@chromium.org,agl@chromium.org
BUG=80797,93654
TEST=ran test_{un,}malicious_fonts.sh
git-svn-id: http://ots.googlecode.com/svn/trunk@71 a4e77c2c-9104-11de-800e-5b313e0d2bf3
diff --git a/src/layout.cc b/src/layout.cc
index 9877e6c..8dea164 100644
--- a/src/layout.cc
+++ b/src/layout.cc
@@ -97,8 +97,8 @@
return OTS_FAILURE();
}
- const unsigned lang_sys_record_end = static_cast<unsigned>(4) +
- lang_sys_count * 6;
+ const unsigned lang_sys_record_end =
+ 6 * static_cast<unsigned>(lang_sys_count) + 4;
if (lang_sys_record_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -146,8 +146,8 @@
return OTS_FAILURE();
}
- const unsigned feature_table_end = static_cast<unsigned>(4) +
- num_lookups * 2;
+ const unsigned feature_table_end =
+ 2 * static_cast<unsigned>(num_lookups) + 4;
if (feature_table_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -210,9 +210,8 @@
subtables.reserve(subtable_count);
// If the |kUseMarkFilteringSetBit| of |lookup_flag| is set,
// extra 2 bytes will follow after subtable offset array.
- const unsigned lookup_table_end =
- static_cast<unsigned>(use_mark_filtering_set ? 8 : 6) +
- subtable_count * 2;
+ const unsigned lookup_table_end = 2 * static_cast<unsigned>(subtable_count) +
+ (use_mark_filtering_set ? 8 : 6);
if (lookup_table_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -471,8 +470,7 @@
if (!subtable.ReadU16(&rule_count)) {
return OTS_FAILURE();
}
- const unsigned rule_end = static_cast<unsigned>(2) +
- rule_count * 2;
+ const unsigned rule_end = 2 * static_cast<unsigned>(rule_count) + 2;
if (rule_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -578,8 +576,8 @@
if (!subtable.ReadU16(&class_rule_count)) {
return OTS_FAILURE();
}
- const unsigned class_rule_end = static_cast<unsigned>(2) +
- class_rule_count * 2;
+ const unsigned class_rule_end =
+ 2 * static_cast<unsigned>(class_rule_count) + 2;
if (class_rule_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -617,8 +615,7 @@
return OTS_FAILURE();
}
- const unsigned class_set_end = static_cast<unsigned>(8) +
- class_set_cnt * 2;
+ const unsigned class_set_end = 2 * static_cast<unsigned>(class_set_cnt) + 8;
if (class_set_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -676,8 +673,8 @@
if (glyph_count >= num_glyphs) {
return OTS_FAILURE();
}
- const unsigned lookup_record_end = static_cast<unsigned>(6) +
- glyph_count * 2 + lookup_count * 4;
+ const unsigned lookup_record_end = 2 * static_cast<unsigned>(glyph_count) +
+ 4 * static_cast<unsigned>(lookup_count) + 6;
if (lookup_record_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -784,8 +781,8 @@
if (!subtable.ReadU16(&chain_rule_count)) {
return OTS_FAILURE();
}
- const unsigned chain_rule_end = static_cast<unsigned>(2) +
- chain_rule_count * 2;
+ const unsigned chain_rule_end =
+ 2 * static_cast<unsigned>(chain_rule_count) + 2;
if (chain_rule_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -821,8 +818,8 @@
return OTS_FAILURE();
}
- const unsigned chain_rule_set_end = static_cast<unsigned>(6) +
- chain_rule_set_count * 2;
+ const unsigned chain_rule_set_end =
+ 2 * static_cast<unsigned>(chain_rule_set_count) + 6;
if (chain_rule_set_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -916,8 +913,8 @@
if (!subtable.ReadU16(&chain_class_rule_count)) {
return OTS_FAILURE();
}
- const unsigned chain_class_rule_end = static_cast<unsigned>(2) +
- chain_class_rule_count * 2;
+ const unsigned chain_class_rule_end =
+ 2 * static_cast<unsigned>(chain_class_rule_count) + 2;
if (chain_class_rule_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -960,8 +957,8 @@
return OTS_FAILURE();
}
- const unsigned chain_class_set_end = static_cast<unsigned>(12) +
- chain_class_set_count * 2;
+ const unsigned chain_class_set_end =
+ 2 * static_cast<unsigned>(chain_class_set_count) + 12;
if (chain_class_set_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -1108,8 +1105,11 @@
}
}
- const unsigned lookup_record_end = static_cast<unsigned>(10) +
- (backtrack_count + input_count + lookahead_count) * 2 + lookup_count * 4;
+ const unsigned lookup_record_end =
+ 2 * (static_cast<unsigned>(backtrack_count) +
+ static_cast<unsigned>(input_count) +
+ static_cast<unsigned>(lookahead_count)) +
+ 4 * static_cast<unsigned>(lookup_count) + 10;
if (lookup_record_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -1175,8 +1175,8 @@
return OTS_FAILURE();
}
- const unsigned script_record_end = static_cast<unsigned>(2) +
- script_count * 6;
+ const unsigned script_record_end =
+ 6 * static_cast<unsigned>(script_count) + 2;
if (script_record_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -1232,8 +1232,8 @@
std::vector<FeatureRecord> feature_records;
feature_records.resize(feature_count);
- const unsigned feature_record_end = static_cast<unsigned>(2) +
- feature_count * 6;
+ const unsigned feature_record_end =
+ 6 * static_cast<unsigned>(feature_count) + 2;
if (feature_record_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}
@@ -1282,8 +1282,8 @@
std::vector<uint16_t> lookups;
lookups.reserve(*num_lookups);
- const unsigned lookup_end = static_cast<unsigned>(2) +
- (*num_lookups) * 2;
+ const unsigned lookup_end =
+ 2 * static_cast<unsigned>(*num_lookups) + 2;
if (lookup_end > std::numeric_limits<uint16_t>::max()) {
return OTS_FAILURE();
}