| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "layout.h" | 5 #include "layout.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "gdef.h" | 10 #include "gdef.h" |
| 11 | 11 |
| 12 // OpenType Layout Common Table Formats | 12 // OpenType Layout Common Table Formats |
| 13 // http://www.microsoft.com/typography/otspec/chapter2.htm | 13 // http://www.microsoft.com/typography/otspec/chapter2.htm |
| 14 | 14 |
| 15 #define TABLE_NAME "Layout" // XXX: use individual table names |
| 16 |
| 15 namespace { | 17 namespace { |
| 16 | 18 |
| 17 // The 'DFLT' tag of script table. | 19 // The 'DFLT' tag of script table. |
| 18 const uint32_t kScriptTableTagDflt = 0x44464c54; | 20 const uint32_t kScriptTableTagDflt = 0x44464c54; |
| 19 // The value which represents there is no required feature index. | 21 // The value which represents there is no required feature index. |
| 20 const uint16_t kNoRequiredFeatureIndexDefined = 0xFFFF; | 22 const uint16_t kNoRequiredFeatureIndexDefined = 0xFFFF; |
| 21 // The lookup flag bit which indicates existence of MarkFilteringSet. | 23 // The lookup flag bit which indicates existence of MarkFilteringSet. |
| 22 const uint16_t kUseMarkFilteringSetBit = 0x0010; | 24 const uint16_t kUseMarkFilteringSetBit = 0x0010; |
| 23 // The lookup flags which require GDEF table. | 25 // The lookup flags which require GDEF table. |
| 24 const uint16_t kGdefRequiredFlags = 0x0002 | 0x0004 | 0x0008; | 26 const uint16_t kGdefRequiredFlags = 0x0002 | 0x0004 | 0x0008; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 37 struct LangSysRecord { | 39 struct LangSysRecord { |
| 38 uint32_t tag; | 40 uint32_t tag; |
| 39 uint16_t offset; | 41 uint16_t offset; |
| 40 }; | 42 }; |
| 41 | 43 |
| 42 struct FeatureRecord { | 44 struct FeatureRecord { |
| 43 uint32_t tag; | 45 uint32_t tag; |
| 44 uint16_t offset; | 46 uint16_t offset; |
| 45 }; | 47 }; |
| 46 | 48 |
| 47 bool ParseLangSysTable(ots::Buffer *subtable, const uint32_t tag, | 49 bool ParseLangSysTable(const ots::OpenTypeFile *file, |
| 50 ots::Buffer *subtable, const uint32_t tag, |
| 48 const uint16_t num_features) { | 51 const uint16_t num_features) { |
| 49 uint16_t offset_lookup_order = 0; | 52 uint16_t offset_lookup_order = 0; |
| 50 uint16_t req_feature_index = 0; | 53 uint16_t req_feature_index = 0; |
| 51 uint16_t feature_count = 0; | 54 uint16_t feature_count = 0; |
| 52 if (!subtable->ReadU16(&offset_lookup_order) || | 55 if (!subtable->ReadU16(&offset_lookup_order) || |
| 53 !subtable->ReadU16(&req_feature_index) || | 56 !subtable->ReadU16(&req_feature_index) || |
| 54 !subtable->ReadU16(&feature_count)) { | 57 !subtable->ReadU16(&feature_count)) { |
| 55 return OTS_FAILURE(); | 58 return OTS_FAILURE_MSG("Failed to read langsys header for tag %4.4s", (char
*)&tag); |
| 56 } | 59 } |
| 57 // |offset_lookup_order| is reserved and should be NULL. | 60 // |offset_lookup_order| is reserved and should be NULL. |
| 58 if (offset_lookup_order != 0) { | 61 if (offset_lookup_order != 0) { |
| 59 return OTS_FAILURE(); | 62 return OTS_FAILURE_MSG("Bad lookup offset order %d for langsys tag %4.4s", o
ffset_lookup_order, (char *)&tag); |
| 60 } | 63 } |
| 61 if (req_feature_index != kNoRequiredFeatureIndexDefined && | 64 if (req_feature_index != kNoRequiredFeatureIndexDefined && |
| 62 req_feature_index >= num_features) { | 65 req_feature_index >= num_features) { |
| 63 return OTS_FAILURE(); | 66 return OTS_FAILURE_MSG("Bad required features index %d for langsys tag %4.4s
", req_feature_index, (char *)&tag); |
| 64 } | 67 } |
| 65 if (feature_count > num_features) { | 68 if (feature_count > num_features) { |
| 66 return OTS_FAILURE(); | 69 return OTS_FAILURE_MSG("Bad feature count %d for langsys tag %4.4s", feature
_count, (char *)&tag); |
| 67 } | 70 } |
| 68 | 71 |
| 69 for (unsigned i = 0; i < feature_count; ++i) { | 72 for (unsigned i = 0; i < feature_count; ++i) { |
| 70 uint16_t feature_index = 0; | 73 uint16_t feature_index = 0; |
| 71 if (!subtable->ReadU16(&feature_index)) { | 74 if (!subtable->ReadU16(&feature_index)) { |
| 72 return OTS_FAILURE(); | 75 return OTS_FAILURE_MSG("Failed to read feature index %d for langsys tag %4
.4s", i, (char *)&tag); |
| 73 } | 76 } |
| 74 if (feature_index >= num_features) { | 77 if (feature_index >= num_features) { |
| 75 return OTS_FAILURE(); | 78 return OTS_FAILURE_MSG("Bad feature index %d for feature %d for langsys ta
g %4.4s", feature_index, i, (char *)&tag); |
| 76 } | 79 } |
| 77 } | 80 } |
| 78 return true; | 81 return true; |
| 79 } | 82 } |
| 80 | 83 |
| 81 bool ParseScriptTable(const uint8_t *data, const size_t length, | 84 bool ParseScriptTable(const ots::OpenTypeFile *file, |
| 85 const uint8_t *data, const size_t length, |
| 82 const uint32_t tag, const uint16_t num_features) { | 86 const uint32_t tag, const uint16_t num_features) { |
| 83 ots::Buffer subtable(data, length); | 87 ots::Buffer subtable(data, length); |
| 84 | 88 |
| 85 uint16_t offset_default_lang_sys = 0; | 89 uint16_t offset_default_lang_sys = 0; |
| 86 uint16_t lang_sys_count = 0; | 90 uint16_t lang_sys_count = 0; |
| 87 if (!subtable.ReadU16(&offset_default_lang_sys) || | 91 if (!subtable.ReadU16(&offset_default_lang_sys) || |
| 88 !subtable.ReadU16(&lang_sys_count)) { | 92 !subtable.ReadU16(&lang_sys_count)) { |
| 89 return OTS_FAILURE(); | 93 return OTS_FAILURE_MSG("Failed to read script header for script tag %4.4s",
(char *)&tag); |
| 90 } | 94 } |
| 91 | 95 |
| 92 // The spec requires a script table for 'DFLT' tag must contain non-NULL | 96 // The spec requires a script table for 'DFLT' tag must contain non-NULL |
| 93 // |offset_default_lang_sys| and |lang_sys_count| == 0 | 97 // |offset_default_lang_sys| and |lang_sys_count| == 0 |
| 94 if (tag == kScriptTableTagDflt && | 98 if (tag == kScriptTableTagDflt && |
| 95 (offset_default_lang_sys == 0 || lang_sys_count != 0)) { | 99 (offset_default_lang_sys == 0 || lang_sys_count != 0)) { |
| 96 OTS_WARNING("DFLT table doesn't satisfy the spec."); | 100 return OTS_FAILURE_MSG("DFLT table doesn't satisfy the spec. for script tag
%4.4s", (char *)&tag); |
| 97 return OTS_FAILURE(); | |
| 98 } | 101 } |
| 99 | 102 |
| 100 const unsigned lang_sys_record_end = | 103 const unsigned lang_sys_record_end = |
| 101 6 * static_cast<unsigned>(lang_sys_count) + 4; | 104 6 * static_cast<unsigned>(lang_sys_count) + 4; |
| 102 if (lang_sys_record_end > std::numeric_limits<uint16_t>::max()) { | 105 if (lang_sys_record_end > std::numeric_limits<uint16_t>::max()) { |
| 103 return OTS_FAILURE(); | 106 return OTS_FAILURE_MSG("Bad end of langsys record %d for script tag %4.4s",
lang_sys_record_end, (char *)&tag); |
| 104 } | 107 } |
| 105 | 108 |
| 106 std::vector<LangSysRecord> lang_sys_records; | 109 std::vector<LangSysRecord> lang_sys_records; |
| 107 lang_sys_records.resize(lang_sys_count); | 110 lang_sys_records.resize(lang_sys_count); |
| 108 uint32_t last_tag = 0; | 111 uint32_t last_tag = 0; |
| 109 for (unsigned i = 0; i < lang_sys_count; ++i) { | 112 for (unsigned i = 0; i < lang_sys_count; ++i) { |
| 110 if (!subtable.ReadU32(&lang_sys_records[i].tag) || | 113 if (!subtable.ReadU32(&lang_sys_records[i].tag) || |
| 111 !subtable.ReadU16(&lang_sys_records[i].offset)) { | 114 !subtable.ReadU16(&lang_sys_records[i].offset)) { |
| 112 return OTS_FAILURE(); | 115 return OTS_FAILURE_MSG("Failed to read langsys record header %d for script
tag %4.4s", i, (char *)&tag); |
| 113 } | 116 } |
| 114 // The record array must store the records alphabetically by tag | 117 // The record array must store the records alphabetically by tag |
| 115 if (last_tag != 0 && last_tag > lang_sys_records[i].tag) { | 118 if (last_tag != 0 && last_tag > lang_sys_records[i].tag) { |
| 116 return OTS_FAILURE(); | 119 return OTS_FAILURE_MSG("Bad last tag %d for langsys record %d for script t
ag %4.4s", last_tag, i, (char *)&tag); |
| 117 } | 120 } |
| 118 if (lang_sys_records[i].offset < lang_sys_record_end || | 121 if (lang_sys_records[i].offset < lang_sys_record_end || |
| 119 lang_sys_records[i].offset >= length) { | 122 lang_sys_records[i].offset >= length) { |
| 120 OTS_WARNING("bad offset to lang sys table: %x", | 123 return OTS_FAILURE_MSG("bad offset to lang sys table: %x", |
| 121 lang_sys_records[i].offset); | 124 lang_sys_records[i].offset); |
| 122 return OTS_FAILURE(); | |
| 123 } | 125 } |
| 124 last_tag = lang_sys_records[i].tag; | 126 last_tag = lang_sys_records[i].tag; |
| 125 } | 127 } |
| 126 | 128 |
| 127 // Check lang sys tables | 129 // Check lang sys tables |
| 128 for (unsigned i = 0; i < lang_sys_count; ++i) { | 130 for (unsigned i = 0; i < lang_sys_count; ++i) { |
| 129 subtable.set_offset(lang_sys_records[i].offset); | 131 subtable.set_offset(lang_sys_records[i].offset); |
| 130 if (!ParseLangSysTable(&subtable, lang_sys_records[i].tag, num_features)) { | 132 if (!ParseLangSysTable(file, &subtable, lang_sys_records[i].tag, num_feature
s)) { |
| 131 return OTS_FAILURE(); | 133 return OTS_FAILURE_MSG("Failed to parse langsys table %d (%4.4s) for scrip
t tag %4.4s", i, (char *)&lang_sys_records[i].tag, (char *)&tag); |
| 132 } | 134 } |
| 133 } | 135 } |
| 134 | 136 |
| 135 return true; | 137 return true; |
| 136 } | 138 } |
| 137 | 139 |
| 138 bool ParseFeatureTable(const uint8_t *data, const size_t length, | 140 bool ParseFeatureTable(const ots::OpenTypeFile *file, |
| 141 const uint8_t *data, const size_t length, |
| 139 const uint16_t num_lookups) { | 142 const uint16_t num_lookups) { |
| 140 ots::Buffer subtable(data, length); | 143 ots::Buffer subtable(data, length); |
| 141 | 144 |
| 142 uint16_t offset_feature_params = 0; | 145 uint16_t offset_feature_params = 0; |
| 143 uint16_t lookup_count = 0; | 146 uint16_t lookup_count = 0; |
| 144 if (!subtable.ReadU16(&offset_feature_params) || | 147 if (!subtable.ReadU16(&offset_feature_params) || |
| 145 !subtable.ReadU16(&lookup_count)) { | 148 !subtable.ReadU16(&lookup_count)) { |
| 146 return OTS_FAILURE(); | 149 return OTS_FAILURE_MSG("Failed to read feature table header"); |
| 147 } | 150 } |
| 148 | 151 |
| 149 const unsigned feature_table_end = | 152 const unsigned feature_table_end = |
| 150 2 * static_cast<unsigned>(lookup_count) + 4; | 153 2 * static_cast<unsigned>(lookup_count) + 4; |
| 151 if (feature_table_end > std::numeric_limits<uint16_t>::max()) { | 154 if (feature_table_end > std::numeric_limits<uint16_t>::max()) { |
| 152 return OTS_FAILURE(); | 155 return OTS_FAILURE_MSG("Bad end of feature table %d", feature_table_end); |
| 153 } | 156 } |
| 154 // |offset_feature_params| is generally set to NULL. | 157 // |offset_feature_params| is generally set to NULL. |
| 155 if (offset_feature_params != 0 && | 158 if (offset_feature_params != 0 && |
| 156 (offset_feature_params < feature_table_end || | 159 (offset_feature_params < feature_table_end || |
| 157 offset_feature_params >= length)) { | 160 offset_feature_params >= length)) { |
| 158 return OTS_FAILURE(); | 161 return OTS_FAILURE_MSG("Bad feature params offset %d", offset_feature_params
); |
| 159 } | 162 } |
| 160 | 163 |
| 161 for (unsigned i = 0; i < lookup_count; ++i) { | 164 for (unsigned i = 0; i < lookup_count; ++i) { |
| 162 uint16_t lookup_index = 0; | 165 uint16_t lookup_index = 0; |
| 163 if (!subtable.ReadU16(&lookup_index)) { | 166 if (!subtable.ReadU16(&lookup_index)) { |
| 164 return OTS_FAILURE(); | 167 return OTS_FAILURE_MSG("Failed to read lookup index for lookup %d", i); |
| 165 } | 168 } |
| 166 // lookup index starts with 0. | 169 // lookup index starts with 0. |
| 167 if (lookup_index >= num_lookups) { | 170 if (lookup_index >= num_lookups) { |
| 168 return OTS_FAILURE(); | 171 return OTS_FAILURE_MSG("Bad lookup index %d for lookup %d", lookup_index,
i); |
| 169 } | 172 } |
| 170 } | 173 } |
| 171 return true; | 174 return true; |
| 172 } | 175 } |
| 173 | 176 |
| 174 bool ParseLookupTable(ots::OpenTypeFile *file, const uint8_t *data, | 177 bool ParseLookupTable(ots::OpenTypeFile *file, const uint8_t *data, |
| 175 const size_t length, | 178 const size_t length, |
| 176 const ots::LookupSubtableParser* parser) { | 179 const ots::LookupSubtableParser* parser) { |
| 177 ots::Buffer subtable(data, length); | 180 ots::Buffer subtable(data, length); |
| 178 | 181 |
| 179 uint16_t lookup_type = 0; | 182 uint16_t lookup_type = 0; |
| 180 uint16_t lookup_flag = 0; | 183 uint16_t lookup_flag = 0; |
| 181 uint16_t subtable_count = 0; | 184 uint16_t subtable_count = 0; |
| 182 if (!subtable.ReadU16(&lookup_type) || | 185 if (!subtable.ReadU16(&lookup_type) || |
| 183 !subtable.ReadU16(&lookup_flag) || | 186 !subtable.ReadU16(&lookup_flag) || |
| 184 !subtable.ReadU16(&subtable_count)) { | 187 !subtable.ReadU16(&subtable_count)) { |
| 185 return OTS_FAILURE(); | 188 return OTS_FAILURE_MSG("Failed to read lookup table header"); |
| 186 } | 189 } |
| 187 | 190 |
| 188 if (lookup_type == 0 || lookup_type > parser->num_types) { | 191 if (lookup_type == 0 || lookup_type > parser->num_types) { |
| 189 return OTS_FAILURE(); | 192 return OTS_FAILURE_MSG("Bad lookup type %d", lookup_type); |
| 190 } | 193 } |
| 191 | 194 |
| 192 // Check lookup flags. | 195 // Check lookup flags. |
| 193 if ((lookup_flag & kGdefRequiredFlags) && | 196 if ((lookup_flag & kGdefRequiredFlags) && |
| 194 (!file->gdef || !file->gdef->has_glyph_class_def)) { | 197 (!file->gdef || !file->gdef->has_glyph_class_def)) { |
| 195 return OTS_FAILURE(); | 198 return OTS_FAILURE_MSG("Bad lookup flags %d", lookup_flag); |
| 196 } | 199 } |
| 197 if ((lookup_flag & kMarkAttachmentTypeMask) && | 200 if ((lookup_flag & kMarkAttachmentTypeMask) && |
| 198 (!file->gdef || !file->gdef->has_mark_attachment_class_def)) { | 201 (!file->gdef || !file->gdef->has_mark_attachment_class_def)) { |
| 199 return OTS_FAILURE(); | 202 return OTS_FAILURE_MSG("lookup flag asks for mark attachment that is bad %d"
, lookup_flag); |
| 200 } | 203 } |
| 201 bool use_mark_filtering_set = false; | 204 bool use_mark_filtering_set = false; |
| 202 if (lookup_flag & kUseMarkFilteringSetBit) { | 205 if (lookup_flag & kUseMarkFilteringSetBit) { |
| 203 if (!file->gdef || !file->gdef->has_mark_glyph_sets_def) { | 206 if (!file->gdef || !file->gdef->has_mark_glyph_sets_def) { |
| 204 return OTS_FAILURE(); | 207 return OTS_FAILURE_MSG("lookup flag asks for mark filtering that is bad %d
", lookup_flag); |
| 205 } | 208 } |
| 206 use_mark_filtering_set = true; | 209 use_mark_filtering_set = true; |
| 207 } | 210 } |
| 208 | 211 |
| 209 std::vector<uint16_t> subtables; | 212 std::vector<uint16_t> subtables; |
| 210 subtables.reserve(subtable_count); | 213 subtables.reserve(subtable_count); |
| 211 // If the |kUseMarkFilteringSetBit| of |lookup_flag| is set, | 214 // If the |kUseMarkFilteringSetBit| of |lookup_flag| is set, |
| 212 // extra 2 bytes will follow after subtable offset array. | 215 // extra 2 bytes will follow after subtable offset array. |
| 213 const unsigned lookup_table_end = 2 * static_cast<unsigned>(subtable_count) + | 216 const unsigned lookup_table_end = 2 * static_cast<unsigned>(subtable_count) + |
| 214 (use_mark_filtering_set ? 8 : 6); | 217 (use_mark_filtering_set ? 8 : 6); |
| 215 if (lookup_table_end > std::numeric_limits<uint16_t>::max()) { | 218 if (lookup_table_end > std::numeric_limits<uint16_t>::max()) { |
| 216 return OTS_FAILURE(); | 219 return OTS_FAILURE_MSG("Bad end of lookup %d", lookup_table_end); |
| 217 } | 220 } |
| 218 for (unsigned i = 0; i < subtable_count; ++i) { | 221 for (unsigned i = 0; i < subtable_count; ++i) { |
| 219 uint16_t offset_subtable = 0; | 222 uint16_t offset_subtable = 0; |
| 220 if (!subtable.ReadU16(&offset_subtable)) { | 223 if (!subtable.ReadU16(&offset_subtable)) { |
| 221 return OTS_FAILURE(); | 224 return OTS_FAILURE_MSG("Failed to read subtable offset %d", i); |
| 222 } | 225 } |
| 223 if (offset_subtable < lookup_table_end || | 226 if (offset_subtable < lookup_table_end || |
| 224 offset_subtable >= length) { | 227 offset_subtable >= length) { |
| 225 return OTS_FAILURE(); | 228 return OTS_FAILURE_MSG("Bad subtable offset %d for subtable %d", offset_su
btable, i); |
| 226 } | 229 } |
| 227 subtables.push_back(offset_subtable); | 230 subtables.push_back(offset_subtable); |
| 228 } | 231 } |
| 229 if (subtables.size() != subtable_count) { | 232 if (subtables.size() != subtable_count) { |
| 230 return OTS_FAILURE(); | 233 return OTS_FAILURE_MSG("Bad subtable size %ld", subtables.size()); |
| 231 } | 234 } |
| 232 | 235 |
| 233 if (use_mark_filtering_set) { | 236 if (use_mark_filtering_set) { |
| 234 uint16_t mark_filtering_set = 0; | 237 uint16_t mark_filtering_set = 0; |
| 235 if (!subtable.ReadU16(&mark_filtering_set)) { | 238 if (!subtable.ReadU16(&mark_filtering_set)) { |
| 236 return OTS_FAILURE(); | 239 return OTS_FAILURE_MSG("Failed to read mark filtering set"); |
| 237 } | 240 } |
| 238 if (file->gdef->num_mark_glyph_sets == 0 || | 241 if (file->gdef->num_mark_glyph_sets == 0 || |
| 239 mark_filtering_set >= file->gdef->num_mark_glyph_sets) { | 242 mark_filtering_set >= file->gdef->num_mark_glyph_sets) { |
| 240 return OTS_FAILURE(); | 243 return OTS_FAILURE_MSG("Bad mark filtering set %d", mark_filtering_set); |
| 241 } | 244 } |
| 242 } | 245 } |
| 243 | 246 |
| 244 // Parse lookup subtables for this lookup type. | 247 // Parse lookup subtables for this lookup type. |
| 245 for (unsigned i = 0; i < subtable_count; ++i) { | 248 for (unsigned i = 0; i < subtable_count; ++i) { |
| 246 if (!parser->Parse(file, data + subtables[i], length - subtables[i], | 249 if (!parser->Parse(file, data + subtables[i], length - subtables[i], |
| 247 lookup_type)) { | 250 lookup_type)) { |
| 248 return OTS_FAILURE(); | 251 return OTS_FAILURE_MSG("Failed to parse subtable %d", i); |
| 249 } | 252 } |
| 250 } | 253 } |
| 251 return true; | 254 return true; |
| 252 } | 255 } |
| 253 | 256 |
| 254 bool ParseClassDefFormat1(const uint8_t *data, size_t length, | 257 bool ParseClassDefFormat1(const ots::OpenTypeFile *file, |
| 258 const uint8_t *data, size_t length, |
| 255 const uint16_t num_glyphs, | 259 const uint16_t num_glyphs, |
| 256 const uint16_t num_classes) { | 260 const uint16_t num_classes) { |
| 257 ots::Buffer subtable(data, length); | 261 ots::Buffer subtable(data, length); |
| 258 | 262 |
| 259 // Skip format field. | 263 // Skip format field. |
| 260 if (!subtable.Skip(2)) { | 264 if (!subtable.Skip(2)) { |
| 261 return OTS_FAILURE(); | 265 return OTS_FAILURE_MSG("Failed to skip class definition header"); |
| 262 } | 266 } |
| 263 | 267 |
| 264 uint16_t start_glyph = 0; | 268 uint16_t start_glyph = 0; |
| 265 if (!subtable.ReadU16(&start_glyph)) { | 269 if (!subtable.ReadU16(&start_glyph)) { |
| 266 return OTS_FAILURE(); | 270 return OTS_FAILURE_MSG("Failed to read starting glyph of class definition"); |
| 267 } | 271 } |
| 268 if (start_glyph > num_glyphs) { | 272 if (start_glyph > num_glyphs) { |
| 269 OTS_WARNING("bad start glyph ID: %u", start_glyph); | 273 return OTS_FAILURE_MSG("Bad starting glyph %d in class definition", start_gl
yph); |
| 270 return OTS_FAILURE(); | |
| 271 } | 274 } |
| 272 | 275 |
| 273 uint16_t glyph_count = 0; | 276 uint16_t glyph_count = 0; |
| 274 if (!subtable.ReadU16(&glyph_count)) { | 277 if (!subtable.ReadU16(&glyph_count)) { |
| 275 return OTS_FAILURE(); | 278 return OTS_FAILURE_MSG("Failed to read glyph count in class definition"); |
| 276 } | 279 } |
| 277 if (glyph_count > num_glyphs) { | 280 if (glyph_count > num_glyphs) { |
| 278 OTS_WARNING("bad glyph count: %u", glyph_count); | 281 return OTS_FAILURE_MSG("bad glyph count: %u", glyph_count); |
| 279 return OTS_FAILURE(); | |
| 280 } | 282 } |
| 281 for (unsigned i = 0; i < glyph_count; ++i) { | 283 for (unsigned i = 0; i < glyph_count; ++i) { |
| 282 uint16_t class_value = 0; | 284 uint16_t class_value = 0; |
| 283 if (!subtable.ReadU16(&class_value)) { | 285 if (!subtable.ReadU16(&class_value)) { |
| 284 return OTS_FAILURE(); | 286 return OTS_FAILURE_MSG("Failed to read class value for glyph %d in class d
efinition", i); |
| 285 } | 287 } |
| 286 if (class_value > num_classes) { | 288 if (class_value > num_classes) { |
| 287 OTS_WARNING("bad class value: %u", class_value); | 289 return OTS_FAILURE_MSG("Bad class value %d for glyph %d in class definitio
n", class_value, i); |
| 288 return OTS_FAILURE(); | |
| 289 } | 290 } |
| 290 } | 291 } |
| 291 | 292 |
| 292 return true; | 293 return true; |
| 293 } | 294 } |
| 294 | 295 |
| 295 bool ParseClassDefFormat2(const uint8_t *data, size_t length, | 296 bool ParseClassDefFormat2(const ots::OpenTypeFile *file, |
| 297 const uint8_t *data, size_t length, |
| 296 const uint16_t num_glyphs, | 298 const uint16_t num_glyphs, |
| 297 const uint16_t num_classes) { | 299 const uint16_t num_classes) { |
| 298 ots::Buffer subtable(data, length); | 300 ots::Buffer subtable(data, length); |
| 299 | 301 |
| 300 // Skip format field. | 302 // Skip format field. |
| 301 if (!subtable.Skip(2)) { | 303 if (!subtable.Skip(2)) { |
| 302 return OTS_FAILURE(); | 304 return OTS_FAILURE_MSG("Failed to skip format of class defintion header"); |
| 303 } | 305 } |
| 304 | 306 |
| 305 uint16_t range_count = 0; | 307 uint16_t range_count = 0; |
| 306 if (!subtable.ReadU16(&range_count)) { | 308 if (!subtable.ReadU16(&range_count)) { |
| 307 return OTS_FAILURE(); | 309 return OTS_FAILURE_MSG("Failed to read range count in class definition"); |
| 308 } | 310 } |
| 309 if (range_count > num_glyphs) { | 311 if (range_count > num_glyphs) { |
| 310 OTS_WARNING("bad range count: %u", range_count); | 312 return OTS_FAILURE_MSG("bad range count: %u", range_count); |
| 311 return OTS_FAILURE(); | |
| 312 } | 313 } |
| 313 | 314 |
| 314 uint16_t last_end = 0; | 315 uint16_t last_end = 0; |
| 315 for (unsigned i = 0; i < range_count; ++i) { | 316 for (unsigned i = 0; i < range_count; ++i) { |
| 316 uint16_t start = 0; | 317 uint16_t start = 0; |
| 317 uint16_t end = 0; | 318 uint16_t end = 0; |
| 318 uint16_t class_value = 0; | 319 uint16_t class_value = 0; |
| 319 if (!subtable.ReadU16(&start) || | 320 if (!subtable.ReadU16(&start) || |
| 320 !subtable.ReadU16(&end) || | 321 !subtable.ReadU16(&end) || |
| 321 !subtable.ReadU16(&class_value)) { | 322 !subtable.ReadU16(&class_value)) { |
| 322 return OTS_FAILURE(); | 323 return OTS_FAILURE_MSG("Failed to read class definition reange %d", i); |
| 323 } | 324 } |
| 324 if (start > end || (last_end && start <= last_end)) { | 325 if (start > end || (last_end && start <= last_end)) { |
| 325 OTS_WARNING("glyph range is overlapping."); | 326 return OTS_FAILURE_MSG("glyph range is overlapping.in range %d", i); |
| 326 return OTS_FAILURE(); | |
| 327 } | 327 } |
| 328 if (class_value > num_classes) { | 328 if (class_value > num_classes) { |
| 329 OTS_WARNING("bad class value: %u", class_value); | 329 return OTS_FAILURE_MSG("bad class value: %u", class_value); |
| 330 return OTS_FAILURE(); | |
| 331 } | 330 } |
| 332 last_end = end; | 331 last_end = end; |
| 333 } | 332 } |
| 334 | 333 |
| 335 return true; | 334 return true; |
| 336 } | 335 } |
| 337 | 336 |
| 338 bool ParseCoverageFormat1(const uint8_t *data, size_t length, | 337 bool ParseCoverageFormat1(const ots::OpenTypeFile *file, |
| 338 const uint8_t *data, size_t length, |
| 339 const uint16_t num_glyphs, | 339 const uint16_t num_glyphs, |
| 340 const uint16_t expected_num_glyphs) { | 340 const uint16_t expected_num_glyphs) { |
| 341 ots::Buffer subtable(data, length); | 341 ots::Buffer subtable(data, length); |
| 342 | 342 |
| 343 // Skip format field. | 343 // Skip format field. |
| 344 if (!subtable.Skip(2)) { | 344 if (!subtable.Skip(2)) { |
| 345 return OTS_FAILURE(); | 345 return OTS_FAILURE_MSG("Failed to skip coverage format"); |
| 346 } | 346 } |
| 347 | 347 |
| 348 uint16_t glyph_count = 0; | 348 uint16_t glyph_count = 0; |
| 349 if (!subtable.ReadU16(&glyph_count)) { | 349 if (!subtable.ReadU16(&glyph_count)) { |
| 350 return OTS_FAILURE(); | 350 return OTS_FAILURE_MSG("Failed to read glyph count in coverage"); |
| 351 } | 351 } |
| 352 if (glyph_count > num_glyphs) { | 352 if (glyph_count > num_glyphs) { |
| 353 OTS_WARNING("bad glyph count: %u", glyph_count); | 353 return OTS_FAILURE_MSG("bad glyph count: %u", glyph_count); |
| 354 return OTS_FAILURE(); | |
| 355 } | 354 } |
| 356 for (unsigned i = 0; i < glyph_count; ++i) { | 355 for (unsigned i = 0; i < glyph_count; ++i) { |
| 357 uint16_t glyph = 0; | 356 uint16_t glyph = 0; |
| 358 if (!subtable.ReadU16(&glyph)) { | 357 if (!subtable.ReadU16(&glyph)) { |
| 359 return OTS_FAILURE(); | 358 return OTS_FAILURE_MSG("Failed to read glyph %d in coverage", i); |
| 360 } | 359 } |
| 361 if (glyph > num_glyphs) { | 360 if (glyph > num_glyphs) { |
| 362 OTS_WARNING("bad glyph ID: %u", glyph); | 361 return OTS_FAILURE_MSG("bad glyph ID: %u", glyph); |
| 363 return OTS_FAILURE(); | |
| 364 } | 362 } |
| 365 } | 363 } |
| 366 | 364 |
| 367 if (expected_num_glyphs && expected_num_glyphs != glyph_count) { | 365 if (expected_num_glyphs && expected_num_glyphs != glyph_count) { |
| 368 OTS_WARNING("unexpected number of glyphs: %u", glyph_count); | 366 return OTS_FAILURE_MSG("unexpected number of glyphs: %u", glyph_count); |
| 369 return OTS_FAILURE(); | |
| 370 } | 367 } |
| 371 | 368 |
| 372 return true; | 369 return true; |
| 373 } | 370 } |
| 374 | 371 |
| 375 bool ParseCoverageFormat2(const uint8_t *data, size_t length, | 372 bool ParseCoverageFormat2(const ots::OpenTypeFile *file, |
| 373 const uint8_t *data, size_t length, |
| 376 const uint16_t num_glyphs, | 374 const uint16_t num_glyphs, |
| 377 const uint16_t expected_num_glyphs) { | 375 const uint16_t expected_num_glyphs) { |
| 378 ots::Buffer subtable(data, length); | 376 ots::Buffer subtable(data, length); |
| 379 | 377 |
| 380 // Skip format field. | 378 // Skip format field. |
| 381 if (!subtable.Skip(2)) { | 379 if (!subtable.Skip(2)) { |
| 382 return OTS_FAILURE(); | 380 return OTS_FAILURE_MSG("Failed to skip format of coverage type 2"); |
| 383 } | 381 } |
| 384 | 382 |
| 385 uint16_t range_count = 0; | 383 uint16_t range_count = 0; |
| 386 if (!subtable.ReadU16(&range_count)) { | 384 if (!subtable.ReadU16(&range_count)) { |
| 387 return OTS_FAILURE(); | 385 return OTS_FAILURE_MSG("Failed to read range count in coverage"); |
| 388 } | 386 } |
| 389 if (range_count > num_glyphs) { | 387 if (range_count > num_glyphs) { |
| 390 OTS_WARNING("bad range count: %u", range_count); | 388 return OTS_FAILURE_MSG("bad range count: %u", range_count); |
| 391 return OTS_FAILURE(); | |
| 392 } | 389 } |
| 393 uint16_t last_end = 0; | 390 uint16_t last_end = 0; |
| 394 uint16_t last_start_coverage_index = 0; | 391 uint16_t last_start_coverage_index = 0; |
| 395 for (unsigned i = 0; i < range_count; ++i) { | 392 for (unsigned i = 0; i < range_count; ++i) { |
| 396 uint16_t start = 0; | 393 uint16_t start = 0; |
| 397 uint16_t end = 0; | 394 uint16_t end = 0; |
| 398 uint16_t start_coverage_index = 0; | 395 uint16_t start_coverage_index = 0; |
| 399 if (!subtable.ReadU16(&start) || | 396 if (!subtable.ReadU16(&start) || |
| 400 !subtable.ReadU16(&end) || | 397 !subtable.ReadU16(&end) || |
| 401 !subtable.ReadU16(&start_coverage_index)) { | 398 !subtable.ReadU16(&start_coverage_index)) { |
| 402 return OTS_FAILURE(); | 399 return OTS_FAILURE_MSG("Failed to read range %d in coverage", i); |
| 403 } | 400 } |
| 404 | 401 |
| 405 // Some of the Adobe Pro fonts have ranges that overlap by one element: the | 402 // Some of the Adobe Pro fonts have ranges that overlap by one element: the |
| 406 // start of one range is equal to the end of the previous range. Therefore | 403 // start of one range is equal to the end of the previous range. Therefore |
| 407 // the < in the following condition should be <= were it not for this. | 404 // the < in the following condition should be <= were it not for this. |
| 408 // See crbug.com/134135. | 405 // See crbug.com/134135. |
| 409 if (start > end || (last_end && start < last_end)) { | 406 if (start > end || (last_end && start < last_end)) { |
| 410 OTS_WARNING("glyph range is overlapping."); | 407 return OTS_FAILURE_MSG("glyph range is overlapping."); |
| 411 return OTS_FAILURE(); | |
| 412 } | 408 } |
| 413 if (start_coverage_index != last_start_coverage_index) { | 409 if (start_coverage_index != last_start_coverage_index) { |
| 414 OTS_WARNING("bad start coverage index."); | 410 return OTS_FAILURE_MSG("bad start coverage index."); |
| 415 return OTS_FAILURE(); | |
| 416 } | 411 } |
| 417 last_end = end; | 412 last_end = end; |
| 418 last_start_coverage_index += end - start + 1; | 413 last_start_coverage_index += end - start + 1; |
| 419 } | 414 } |
| 420 | 415 |
| 421 if (expected_num_glyphs && | 416 if (expected_num_glyphs && |
| 422 expected_num_glyphs != last_start_coverage_index) { | 417 expected_num_glyphs != last_start_coverage_index) { |
| 423 OTS_WARNING("unexpected number of glyphs: %u", last_start_coverage_index); | 418 return OTS_FAILURE_MSG("unexpected number of glyphs: %u", last_start_cover
age_index); |
| 424 return OTS_FAILURE(); | |
| 425 } | 419 } |
| 426 | 420 |
| 427 return true; | 421 return true; |
| 428 } | 422 } |
| 429 | 423 |
| 430 // Parsers for Contextual subtables in GSUB/GPOS tables. | 424 // Parsers for Contextual subtables in GSUB/GPOS tables. |
| 431 | 425 |
| 432 bool ParseLookupRecord(ots::Buffer *subtable, const uint16_t num_glyphs, | 426 bool ParseLookupRecord(const ots::OpenTypeFile *file, |
| 427 ots::Buffer *subtable, const uint16_t num_glyphs, |
| 433 const uint16_t num_lookups) { | 428 const uint16_t num_lookups) { |
| 434 uint16_t sequence_index = 0; | 429 uint16_t sequence_index = 0; |
| 435 uint16_t lookup_list_index = 0; | 430 uint16_t lookup_list_index = 0; |
| 436 if (!subtable->ReadU16(&sequence_index) || | 431 if (!subtable->ReadU16(&sequence_index) || |
| 437 !subtable->ReadU16(&lookup_list_index)) { | 432 !subtable->ReadU16(&lookup_list_index)) { |
| 438 return OTS_FAILURE(); | 433 return OTS_FAILURE_MSG("Failed to read header for lookup record"); |
| 439 } | 434 } |
| 440 if (sequence_index >= num_glyphs) { | 435 if (sequence_index >= num_glyphs) { |
| 441 return OTS_FAILURE(); | 436 return OTS_FAILURE_MSG("Bad sequence index %d in lookup record", sequence_in
dex); |
| 442 } | 437 } |
| 443 if (lookup_list_index >= num_lookups) { | 438 if (lookup_list_index >= num_lookups) { |
| 444 return OTS_FAILURE(); | 439 return OTS_FAILURE_MSG("Bad lookup list index %d in lookup record", lookup_l
ist_index); |
| 445 } | 440 } |
| 446 return true; | 441 return true; |
| 447 } | 442 } |
| 448 | 443 |
| 449 bool ParseRuleSubtable(const uint8_t *data, const size_t length, | 444 bool ParseRuleSubtable(const ots::OpenTypeFile *file, |
| 445 const uint8_t *data, const size_t length, |
| 450 const uint16_t num_glyphs, | 446 const uint16_t num_glyphs, |
| 451 const uint16_t num_lookups) { | 447 const uint16_t num_lookups) { |
| 452 ots::Buffer subtable(data, length); | 448 ots::Buffer subtable(data, length); |
| 453 | 449 |
| 454 uint16_t glyph_count = 0; | 450 uint16_t glyph_count = 0; |
| 455 uint16_t lookup_count = 0; | 451 uint16_t lookup_count = 0; |
| 456 if (!subtable.ReadU16(&glyph_count) || | 452 if (!subtable.ReadU16(&glyph_count) || |
| 457 !subtable.ReadU16(&lookup_count)) { | 453 !subtable.ReadU16(&lookup_count)) { |
| 458 return OTS_FAILURE(); | 454 return OTS_FAILURE_MSG("Failed to read rule subtable header"); |
| 459 } | 455 } |
| 460 | 456 |
| 461 if (glyph_count == 0 || glyph_count >= num_glyphs) { | 457 if (glyph_count == 0 || glyph_count >= num_glyphs) { |
| 462 return OTS_FAILURE(); | 458 return OTS_FAILURE_MSG("Bad glyph count %d in rule subtable", glyph_count); |
| 463 } | 459 } |
| 464 for (unsigned i = 0; i < glyph_count - static_cast<unsigned>(1); ++i) { | 460 for (unsigned i = 0; i < glyph_count - static_cast<unsigned>(1); ++i) { |
| 465 uint16_t glyph_id = 0; | 461 uint16_t glyph_id = 0; |
| 466 if (!subtable.ReadU16(&glyph_id)) { | 462 if (!subtable.ReadU16(&glyph_id)) { |
| 467 return OTS_FAILURE(); | 463 return OTS_FAILURE_MSG("Failed to read glyph %d", i); |
| 468 } | 464 } |
| 469 if (glyph_id > num_glyphs) { | 465 if (glyph_id > num_glyphs) { |
| 470 return OTS_FAILURE(); | 466 return OTS_FAILURE_MSG("Bad glyph %d for entry %d", glyph_id, i); |
| 471 } | 467 } |
| 472 } | 468 } |
| 473 | 469 |
| 474 for (unsigned i = 0; i < lookup_count; ++i) { | 470 for (unsigned i = 0; i < lookup_count; ++i) { |
| 475 if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) { | 471 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { |
| 476 return OTS_FAILURE(); | 472 return OTS_FAILURE_MSG("Failed to parse lookup record %d", i); |
| 477 } | 473 } |
| 478 } | 474 } |
| 479 return true; | 475 return true; |
| 480 } | 476 } |
| 481 | 477 |
| 482 bool ParseRuleSetTable(const uint8_t *data, const size_t length, | 478 bool ParseRuleSetTable(const ots::OpenTypeFile *file, |
| 479 const uint8_t *data, const size_t length, |
| 483 const uint16_t num_glyphs, | 480 const uint16_t num_glyphs, |
| 484 const uint16_t num_lookups) { | 481 const uint16_t num_lookups) { |
| 485 ots::Buffer subtable(data, length); | 482 ots::Buffer subtable(data, length); |
| 486 | 483 |
| 487 uint16_t rule_count = 0; | 484 uint16_t rule_count = 0; |
| 488 if (!subtable.ReadU16(&rule_count)) { | 485 if (!subtable.ReadU16(&rule_count)) { |
| 489 return OTS_FAILURE(); | 486 return OTS_FAILURE_MSG("Failed to read rule count in rule set"); |
| 490 } | 487 } |
| 491 const unsigned rule_end = 2 * static_cast<unsigned>(rule_count) + 2; | 488 const unsigned rule_end = 2 * static_cast<unsigned>(rule_count) + 2; |
| 492 if (rule_end > std::numeric_limits<uint16_t>::max()) { | 489 if (rule_end > std::numeric_limits<uint16_t>::max()) { |
| 493 return OTS_FAILURE(); | 490 return OTS_FAILURE_MSG("Bad end of rule %d in rule set", rule_end); |
| 494 } | 491 } |
| 495 | 492 |
| 496 for (unsigned i = 0; i < rule_count; ++i) { | 493 for (unsigned i = 0; i < rule_count; ++i) { |
| 497 uint16_t offset_rule = 0; | 494 uint16_t offset_rule = 0; |
| 498 if (!subtable.ReadU16(&offset_rule)) { | 495 if (!subtable.ReadU16(&offset_rule)) { |
| 499 return OTS_FAILURE(); | 496 return OTS_FAILURE_MSG("Failed to read rule offset for rule set %d", i); |
| 500 } | 497 } |
| 501 if (offset_rule < rule_end || offset_rule >= length) { | 498 if (offset_rule < rule_end || offset_rule >= length) { |
| 502 return OTS_FAILURE(); | 499 return OTS_FAILURE_MSG("Bad rule offset %d in set %d", offset_rule, i); |
| 503 } | 500 } |
| 504 if (!ParseRuleSubtable(data + offset_rule, length - offset_rule, | 501 if (!ParseRuleSubtable(file, data + offset_rule, length - offset_rule, |
| 505 num_glyphs, num_lookups)) { | 502 num_glyphs, num_lookups)) { |
| 506 return OTS_FAILURE(); | 503 return OTS_FAILURE_MSG("Failed to parse rule set %d", i); |
| 507 } | 504 } |
| 508 } | 505 } |
| 509 | 506 |
| 510 return true; | 507 return true; |
| 511 } | 508 } |
| 512 | 509 |
| 513 bool ParseContextFormat1(const uint8_t *data, const size_t length, | 510 bool ParseContextFormat1(const ots::OpenTypeFile *file, |
| 511 const uint8_t *data, const size_t length, |
| 514 const uint16_t num_glyphs, | 512 const uint16_t num_glyphs, |
| 515 const uint16_t num_lookups) { | 513 const uint16_t num_lookups) { |
| 516 ots::Buffer subtable(data, length); | 514 ots::Buffer subtable(data, length); |
| 517 | 515 |
| 518 uint16_t offset_coverage = 0; | 516 uint16_t offset_coverage = 0; |
| 519 uint16_t rule_set_count = 0; | 517 uint16_t rule_set_count = 0; |
| 520 // Skip format field. | 518 // Skip format field. |
| 521 if (!subtable.Skip(2) || | 519 if (!subtable.Skip(2) || |
| 522 !subtable.ReadU16(&offset_coverage) || | 520 !subtable.ReadU16(&offset_coverage) || |
| 523 !subtable.ReadU16(&rule_set_count)) { | 521 !subtable.ReadU16(&rule_set_count)) { |
| 524 return OTS_FAILURE(); | 522 return OTS_FAILURE_MSG("Failed to read header of context format 1"); |
| 525 } | 523 } |
| 526 | 524 |
| 527 const unsigned rule_set_end = static_cast<unsigned>(6) + | 525 const unsigned rule_set_end = static_cast<unsigned>(6) + |
| 528 rule_set_count * 2; | 526 rule_set_count * 2; |
| 529 if (rule_set_end > std::numeric_limits<uint16_t>::max()) { | 527 if (rule_set_end > std::numeric_limits<uint16_t>::max()) { |
| 530 return OTS_FAILURE(); | 528 return OTS_FAILURE_MSG("Bad end of rule set %d of context format 1", rule_se
t_end); |
| 531 } | 529 } |
| 532 if (offset_coverage < rule_set_end || offset_coverage >= length) { | 530 if (offset_coverage < rule_set_end || offset_coverage >= length) { |
| 533 return OTS_FAILURE(); | 531 return OTS_FAILURE_MSG("Bad coverage offset %d in context format 1", offset_
coverage); |
| 534 } | 532 } |
| 535 if (!ots::ParseCoverageTable(data + offset_coverage, | 533 if (!ots::ParseCoverageTable(file, data + offset_coverage, |
| 536 length - offset_coverage, num_glyphs)) { | 534 length - offset_coverage, num_glyphs)) { |
| 537 return OTS_FAILURE(); | 535 return OTS_FAILURE_MSG("Failed to parse coverage table in context format 1")
; |
| 538 } | 536 } |
| 539 | 537 |
| 540 for (unsigned i = 0; i < rule_set_count; ++i) { | 538 for (unsigned i = 0; i < rule_set_count; ++i) { |
| 541 uint16_t offset_rule = 0; | 539 uint16_t offset_rule = 0; |
| 542 if (!subtable.ReadU16(&offset_rule)) { | 540 if (!subtable.ReadU16(&offset_rule)) { |
| 543 return OTS_FAILURE(); | 541 return OTS_FAILURE_MSG("Failed to read rule offset %d in context format 1"
, i); |
| 544 } | 542 } |
| 545 if (offset_rule < rule_set_end || offset_rule >= length) { | 543 if (offset_rule < rule_set_end || offset_rule >= length) { |
| 546 return OTS_FAILURE(); | 544 return OTS_FAILURE_MSG("Bad rule offset %d in rule %d in context format 1"
, offset_rule, i); |
| 547 } | 545 } |
| 548 if (!ParseRuleSetTable(data + offset_rule, length - offset_rule, | 546 if (!ParseRuleSetTable(file, data + offset_rule, length - offset_rule, |
| 549 num_glyphs, num_lookups)) { | 547 num_glyphs, num_lookups)) { |
| 550 return OTS_FAILURE(); | 548 return OTS_FAILURE_MSG("Failed to parse rule set %d in context format 1",
i); |
| 551 } | 549 } |
| 552 } | 550 } |
| 553 | 551 |
| 554 return true; | 552 return true; |
| 555 } | 553 } |
| 556 | 554 |
| 557 bool ParseClassRuleTable(const uint8_t *data, const size_t length, | 555 bool ParseClassRuleTable(const ots::OpenTypeFile *file, |
| 556 const uint8_t *data, const size_t length, |
| 558 const uint16_t num_glyphs, | 557 const uint16_t num_glyphs, |
| 559 const uint16_t num_lookups) { | 558 const uint16_t num_lookups) { |
| 560 ots::Buffer subtable(data, length); | 559 ots::Buffer subtable(data, length); |
| 561 | 560 |
| 562 uint16_t glyph_count = 0; | 561 uint16_t glyph_count = 0; |
| 563 uint16_t lookup_count = 0; | 562 uint16_t lookup_count = 0; |
| 564 if (!subtable.ReadU16(&glyph_count) || | 563 if (!subtable.ReadU16(&glyph_count) || |
| 565 !subtable.ReadU16(&lookup_count)) { | 564 !subtable.ReadU16(&lookup_count)) { |
| 566 return OTS_FAILURE(); | 565 return OTS_FAILURE_MSG("Failed to read header of class rule table"); |
| 567 } | 566 } |
| 568 | 567 |
| 569 if (glyph_count == 0 || glyph_count >= num_glyphs) { | 568 if (glyph_count == 0 || glyph_count >= num_glyphs) { |
| 570 return OTS_FAILURE(); | 569 return OTS_FAILURE_MSG("Bad glyph count %d in class rule table", glyph_count
); |
| 571 } | 570 } |
| 572 | 571 |
| 573 // ClassRule table contains an array of classes. Each value of classes | 572 // ClassRule table contains an array of classes. Each value of classes |
| 574 // could take arbitrary values including zero so we don't check these value. | 573 // could take arbitrary values including zero so we don't check these value. |
| 575 const unsigned num_classes = glyph_count - static_cast<unsigned>(1); | 574 const unsigned num_classes = glyph_count - static_cast<unsigned>(1); |
| 576 if (!subtable.Skip(2 * num_classes)) { | 575 if (!subtable.Skip(2 * num_classes)) { |
| 577 return OTS_FAILURE(); | 576 return OTS_FAILURE_MSG("Failed to skip classes in class rule table"); |
| 578 } | 577 } |
| 579 | 578 |
| 580 for (unsigned i = 0; i < lookup_count; ++i) { | 579 for (unsigned i = 0; i < lookup_count; ++i) { |
| 581 if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) { | 580 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { |
| 582 return OTS_FAILURE(); | 581 return OTS_FAILURE_MSG("Failed to parse lookup record %d in class rule tab
le", i); |
| 583 } | 582 } |
| 584 } | 583 } |
| 585 return true; | 584 return true; |
| 586 } | 585 } |
| 587 | 586 |
| 588 bool ParseClassSetTable(const uint8_t *data, const size_t length, | 587 bool ParseClassSetTable(const ots::OpenTypeFile *file, |
| 588 const uint8_t *data, const size_t length, |
| 589 const uint16_t num_glyphs, | 589 const uint16_t num_glyphs, |
| 590 const uint16_t num_lookups) { | 590 const uint16_t num_lookups) { |
| 591 ots::Buffer subtable(data, length); | 591 ots::Buffer subtable(data, length); |
| 592 | 592 |
| 593 uint16_t class_rule_count = 0; | 593 uint16_t class_rule_count = 0; |
| 594 if (!subtable.ReadU16(&class_rule_count)) { | 594 if (!subtable.ReadU16(&class_rule_count)) { |
| 595 return OTS_FAILURE(); | 595 return OTS_FAILURE_MSG("Failed to read class rule count in class set table")
; |
| 596 } | 596 } |
| 597 const unsigned class_rule_end = | 597 const unsigned class_rule_end = |
| 598 2 * static_cast<unsigned>(class_rule_count) + 2; | 598 2 * static_cast<unsigned>(class_rule_count) + 2; |
| 599 if (class_rule_end > std::numeric_limits<uint16_t>::max()) { | 599 if (class_rule_end > std::numeric_limits<uint16_t>::max()) { |
| 600 return OTS_FAILURE(); | 600 return OTS_FAILURE_MSG("bad class rule end %d in class set table", class_rul
e_end); |
| 601 } | 601 } |
| 602 for (unsigned i = 0; i < class_rule_count; ++i) { | 602 for (unsigned i = 0; i < class_rule_count; ++i) { |
| 603 uint16_t offset_class_rule = 0; | 603 uint16_t offset_class_rule = 0; |
| 604 if (!subtable.ReadU16(&offset_class_rule)) { | 604 if (!subtable.ReadU16(&offset_class_rule)) { |
| 605 return OTS_FAILURE(); | 605 return OTS_FAILURE_MSG("Failed to read class rule offset %d in class set t
able", i); |
| 606 } | 606 } |
| 607 if (offset_class_rule < class_rule_end || offset_class_rule >= length) { | 607 if (offset_class_rule < class_rule_end || offset_class_rule >= length) { |
| 608 return OTS_FAILURE(); | 608 return OTS_FAILURE_MSG("Bad class rule offset %d in class %d", offset_clas
s_rule, i); |
| 609 } | 609 } |
| 610 if (!ParseClassRuleTable(data + offset_class_rule, | 610 if (!ParseClassRuleTable(file, data + offset_class_rule, |
| 611 length - offset_class_rule, num_glyphs, | 611 length - offset_class_rule, num_glyphs, |
| 612 num_lookups)) { | 612 num_lookups)) { |
| 613 return OTS_FAILURE(); | 613 return OTS_FAILURE_MSG("Failed to parse class rule table %d", i); |
| 614 } | 614 } |
| 615 } | 615 } |
| 616 | 616 |
| 617 return true; | 617 return true; |
| 618 } | 618 } |
| 619 | 619 |
| 620 bool ParseContextFormat2(const uint8_t *data, const size_t length, | 620 bool ParseContextFormat2(const ots::OpenTypeFile *file, |
| 621 const uint16_t num_glyphs, | 621 const uint8_t *data, const size_t length, |
| 622 const uint16_t num_lookups) { | 622 const uint16_t num_glyphs, |
| 623 const uint16_t num_lookups) { |
| 623 ots::Buffer subtable(data, length); | 624 ots::Buffer subtable(data, length); |
| 624 | 625 |
| 625 uint16_t offset_coverage = 0; | 626 uint16_t offset_coverage = 0; |
| 626 uint16_t offset_class_def = 0; | 627 uint16_t offset_class_def = 0; |
| 627 uint16_t class_set_cnt = 0; | 628 uint16_t class_set_cnt = 0; |
| 628 // Skip format field. | 629 // Skip format field. |
| 629 if (!subtable.Skip(2) || | 630 if (!subtable.Skip(2) || |
| 630 !subtable.ReadU16(&offset_coverage) || | 631 !subtable.ReadU16(&offset_coverage) || |
| 631 !subtable.ReadU16(&offset_class_def) || | 632 !subtable.ReadU16(&offset_class_def) || |
| 632 !subtable.ReadU16(&class_set_cnt)) { | 633 !subtable.ReadU16(&class_set_cnt)) { |
| 633 return OTS_FAILURE(); | 634 return OTS_FAILURE_MSG("Failed to read header for context format 2"); |
| 634 } | 635 } |
| 635 | 636 |
| 636 const unsigned class_set_end = 2 * static_cast<unsigned>(class_set_cnt) + 8; | 637 const unsigned class_set_end = 2 * static_cast<unsigned>(class_set_cnt) + 8; |
| 637 if (class_set_end > std::numeric_limits<uint16_t>::max()) { | 638 if (class_set_end > std::numeric_limits<uint16_t>::max()) { |
| 638 return OTS_FAILURE(); | 639 return OTS_FAILURE_MSG("Bad end of class set %d for context format 2", class
_set_end); |
| 639 } | 640 } |
| 640 if (offset_coverage < class_set_end || offset_coverage >= length) { | 641 if (offset_coverage < class_set_end || offset_coverage >= length) { |
| 641 return OTS_FAILURE(); | 642 return OTS_FAILURE_MSG("Bad coverage offset %d in context format 2", offset_
coverage); |
| 642 } | 643 } |
| 643 if (!ots::ParseCoverageTable(data + offset_coverage, | 644 if (!ots::ParseCoverageTable(file, data + offset_coverage, |
| 644 length - offset_coverage, num_glyphs)) { | 645 length - offset_coverage, num_glyphs)) { |
| 645 return OTS_FAILURE(); | 646 return OTS_FAILURE_MSG("Failed to parse coverage table in context format 2")
; |
| 646 } | 647 } |
| 647 | 648 |
| 648 if (offset_class_def < class_set_end || offset_class_def >= length) { | 649 if (offset_class_def < class_set_end || offset_class_def >= length) { |
| 649 return OTS_FAILURE(); | 650 return OTS_FAILURE_MSG("bad class definition offset %d in context format 2",
offset_class_def); |
| 650 } | 651 } |
| 651 if (!ots::ParseClassDefTable(data + offset_class_def, | 652 if (!ots::ParseClassDefTable(file, data + offset_class_def, |
| 652 length - offset_class_def, | 653 length - offset_class_def, |
| 653 num_glyphs, kMaxClassDefValue)) { | 654 num_glyphs, kMaxClassDefValue)) { |
| 654 return OTS_FAILURE(); | 655 return OTS_FAILURE_MSG("Failed to parse class definition table in context fo
rmat 2"); |
| 655 } | 656 } |
| 656 | 657 |
| 657 for (unsigned i = 0; i < class_set_cnt; ++i) { | 658 for (unsigned i = 0; i < class_set_cnt; ++i) { |
| 658 uint16_t offset_class_rule = 0; | 659 uint16_t offset_class_rule = 0; |
| 659 if (!subtable.ReadU16(&offset_class_rule)) { | 660 if (!subtable.ReadU16(&offset_class_rule)) { |
| 660 return OTS_FAILURE(); | 661 return OTS_FAILURE_MSG("Failed to read class rule offset %d in context for
mat 2", i); |
| 661 } | 662 } |
| 662 if (offset_class_rule) { | 663 if (offset_class_rule) { |
| 663 if (offset_class_rule < class_set_end || offset_class_rule >= length) { | 664 if (offset_class_rule < class_set_end || offset_class_rule >= length) { |
| 664 return OTS_FAILURE(); | 665 return OTS_FAILURE_MSG("Bad class rule offset %d for rule %d in context
format 2", offset_class_rule, i); |
| 665 } | 666 } |
| 666 if (!ParseClassSetTable(data + offset_class_rule, | 667 if (!ParseClassSetTable(file, data + offset_class_rule, |
| 667 length - offset_class_rule, num_glyphs, | 668 length - offset_class_rule, num_glyphs, |
| 668 num_lookups)) { | 669 num_lookups)) { |
| 669 return OTS_FAILURE(); | 670 return OTS_FAILURE_MSG("Failed to parse class set %d in context format 2
", i); |
| 670 } | 671 } |
| 671 } | 672 } |
| 672 } | 673 } |
| 673 | 674 |
| 674 return true; | 675 return true; |
| 675 } | 676 } |
| 676 | 677 |
| 677 bool ParseContextFormat3(const uint8_t *data, const size_t length, | 678 bool ParseContextFormat3(const ots::OpenTypeFile *file, |
| 679 const uint8_t *data, const size_t length, |
| 678 const uint16_t num_glyphs, | 680 const uint16_t num_glyphs, |
| 679 const uint16_t num_lookups) { | 681 const uint16_t num_lookups) { |
| 680 ots::Buffer subtable(data, length); | 682 ots::Buffer subtable(data, length); |
| 681 | 683 |
| 682 uint16_t glyph_count = 0; | 684 uint16_t glyph_count = 0; |
| 683 uint16_t lookup_count = 0; | 685 uint16_t lookup_count = 0; |
| 684 // Skip format field. | 686 // Skip format field. |
| 685 if (!subtable.Skip(2) || | 687 if (!subtable.Skip(2) || |
| 686 !subtable.ReadU16(&glyph_count) || | 688 !subtable.ReadU16(&glyph_count) || |
| 687 !subtable.ReadU16(&lookup_count)) { | 689 !subtable.ReadU16(&lookup_count)) { |
| 688 return OTS_FAILURE(); | 690 return OTS_FAILURE_MSG("Failed to read header in context format 3"); |
| 689 } | 691 } |
| 690 | 692 |
| 691 if (glyph_count >= num_glyphs) { | 693 if (glyph_count >= num_glyphs) { |
| 692 return OTS_FAILURE(); | 694 return OTS_FAILURE_MSG("Bad glyph count %d in context format 3", glyph_count
); |
| 693 } | 695 } |
| 694 const unsigned lookup_record_end = 2 * static_cast<unsigned>(glyph_count) + | 696 const unsigned lookup_record_end = 2 * static_cast<unsigned>(glyph_count) + |
| 695 4 * static_cast<unsigned>(lookup_count) + 6; | 697 4 * static_cast<unsigned>(lookup_count) + 6; |
| 696 if (lookup_record_end > std::numeric_limits<uint16_t>::max()) { | 698 if (lookup_record_end > std::numeric_limits<uint16_t>::max()) { |
| 697 return OTS_FAILURE(); | 699 return OTS_FAILURE_MSG("Bad end of lookup %d in context format 3", lookup_re
cord_end); |
| 698 } | 700 } |
| 699 for (unsigned i = 0; i < glyph_count; ++i) { | 701 for (unsigned i = 0; i < glyph_count; ++i) { |
| 700 uint16_t offset_coverage = 0; | 702 uint16_t offset_coverage = 0; |
| 701 if (!subtable.ReadU16(&offset_coverage)) { | 703 if (!subtable.ReadU16(&offset_coverage)) { |
| 702 return OTS_FAILURE(); | 704 return OTS_FAILURE_MSG("Failed to read coverage offset %d in conxtext form
at 3", i); |
| 703 } | 705 } |
| 704 if (offset_coverage < lookup_record_end || offset_coverage >= length) { | 706 if (offset_coverage < lookup_record_end || offset_coverage >= length) { |
| 705 return OTS_FAILURE(); | 707 return OTS_FAILURE_MSG("Bad coverage offset %d for glyph %d in context for
mat 3", offset_coverage, i); |
| 706 } | 708 } |
| 707 if (!ots::ParseCoverageTable(data + offset_coverage, | 709 if (!ots::ParseCoverageTable(file, data + offset_coverage, |
| 708 length - offset_coverage, num_glyphs)) { | 710 length - offset_coverage, num_glyphs)) { |
| 709 return OTS_FAILURE(); | 711 return OTS_FAILURE_MSG("Failed to parse coverage table for glyph %d in con
text format 3", i); |
| 710 } | 712 } |
| 711 } | 713 } |
| 712 | 714 |
| 713 for (unsigned i = 0; i < lookup_count; ++i) { | 715 for (unsigned i = 0; i < lookup_count; ++i) { |
| 714 if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) { | 716 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { |
| 715 return OTS_FAILURE(); | 717 return OTS_FAILURE_MSG("Failed to parse lookup record %d in context format
3", i); |
| 716 } | 718 } |
| 717 } | 719 } |
| 718 | 720 |
| 719 return true; | 721 return true; |
| 720 } | 722 } |
| 721 | 723 |
| 722 // Parsers for Chaning Contextual subtables in GSUB/GPOS tables. | 724 // Parsers for Chaning Contextual subtables in GSUB/GPOS tables. |
| 723 | 725 |
| 724 bool ParseChainRuleSubtable(const uint8_t *data, const size_t length, | 726 bool ParseChainRuleSubtable(const ots::OpenTypeFile *file, |
| 727 const uint8_t *data, const size_t length, |
| 725 const uint16_t num_glyphs, | 728 const uint16_t num_glyphs, |
| 726 const uint16_t num_lookups) { | 729 const uint16_t num_lookups) { |
| 727 ots::Buffer subtable(data, length); | 730 ots::Buffer subtable(data, length); |
| 728 | 731 |
| 729 uint16_t backtrack_count = 0; | 732 uint16_t backtrack_count = 0; |
| 730 if (!subtable.ReadU16(&backtrack_count)) { | 733 if (!subtable.ReadU16(&backtrack_count)) { |
| 731 return OTS_FAILURE(); | 734 return OTS_FAILURE_MSG("Failed to read backtrack count in chain rule subtabl
e"); |
| 732 } | 735 } |
| 733 if (backtrack_count >= num_glyphs) { | 736 if (backtrack_count >= num_glyphs) { |
| 734 return OTS_FAILURE(); | 737 return OTS_FAILURE_MSG("Bad backtrack count %d in chain rule subtable", back
track_count); |
| 735 } | 738 } |
| 736 for (unsigned i = 0; i < backtrack_count; ++i) { | 739 for (unsigned i = 0; i < backtrack_count; ++i) { |
| 737 uint16_t glyph_id = 0; | 740 uint16_t glyph_id = 0; |
| 738 if (!subtable.ReadU16(&glyph_id)) { | 741 if (!subtable.ReadU16(&glyph_id)) { |
| 739 return OTS_FAILURE(); | 742 return OTS_FAILURE_MSG("Failed to read backtrack glyph %d in chain rule su
btable", i); |
| 740 } | 743 } |
| 741 if (glyph_id > num_glyphs) { | 744 if (glyph_id > num_glyphs) { |
| 742 return OTS_FAILURE(); | 745 return OTS_FAILURE_MSG("Bad glyph id %d for bactrack glyph %d in chain rul
e subtable", glyph_id, i); |
| 743 } | 746 } |
| 744 } | 747 } |
| 745 | 748 |
| 746 uint16_t input_count = 0; | 749 uint16_t input_count = 0; |
| 747 if (!subtable.ReadU16(&input_count)) { | 750 if (!subtable.ReadU16(&input_count)) { |
| 748 return OTS_FAILURE(); | 751 return OTS_FAILURE_MSG("Failed to read input count in chain rule subtable"); |
| 749 } | 752 } |
| 750 if (input_count == 0 || input_count >= num_glyphs) { | 753 if (input_count == 0 || input_count >= num_glyphs) { |
| 751 return OTS_FAILURE(); | 754 return OTS_FAILURE_MSG("Bad input count %d in chain rule subtable", input_co
unt); |
| 752 } | 755 } |
| 753 for (unsigned i = 0; i < input_count - static_cast<unsigned>(1); ++i) { | 756 for (unsigned i = 0; i < input_count - static_cast<unsigned>(1); ++i) { |
| 754 uint16_t glyph_id = 0; | 757 uint16_t glyph_id = 0; |
| 755 if (!subtable.ReadU16(&glyph_id)) { | 758 if (!subtable.ReadU16(&glyph_id)) { |
| 756 return OTS_FAILURE(); | 759 return OTS_FAILURE_MSG("Failed to read input glyph %d in chain rule subtab
le", i); |
| 757 } | 760 } |
| 758 if (glyph_id > num_glyphs) { | 761 if (glyph_id > num_glyphs) { |
| 759 return OTS_FAILURE(); | 762 return OTS_FAILURE_MSG("Bad glyph id %d for input glyph %d in chain rule s
ubtable", glyph_id, i); |
| 760 } | 763 } |
| 761 } | 764 } |
| 762 | 765 |
| 763 uint16_t lookahead_count = 0; | 766 uint16_t lookahead_count = 0; |
| 764 if (!subtable.ReadU16(&lookahead_count)) { | 767 if (!subtable.ReadU16(&lookahead_count)) { |
| 765 return OTS_FAILURE(); | 768 return OTS_FAILURE_MSG("Failed to read lookahead count in chain rule subtabl
e"); |
| 766 } | 769 } |
| 767 if (lookahead_count >= num_glyphs) { | 770 if (lookahead_count >= num_glyphs) { |
| 768 return OTS_FAILURE(); | 771 return OTS_FAILURE_MSG("Bad lookahead count %d in chain rule subtable", look
ahead_count); |
| 769 } | 772 } |
| 770 for (unsigned i = 0; i < lookahead_count; ++i) { | 773 for (unsigned i = 0; i < lookahead_count; ++i) { |
| 771 uint16_t glyph_id = 0; | 774 uint16_t glyph_id = 0; |
| 772 if (!subtable.ReadU16(&glyph_id)) { | 775 if (!subtable.ReadU16(&glyph_id)) { |
| 773 return OTS_FAILURE(); | 776 return OTS_FAILURE_MSG("Failed to read lookahead glyph %d in chain rule su
btable", i); |
| 774 } | 777 } |
| 775 if (glyph_id > num_glyphs) { | 778 if (glyph_id > num_glyphs) { |
| 776 return OTS_FAILURE(); | 779 return OTS_FAILURE_MSG("Bad glyph id %d for lookadhead glyph %d in chain r
ule subtable", glyph_id, i); |
| 777 } | 780 } |
| 778 } | 781 } |
| 779 | 782 |
| 780 uint16_t lookup_count = 0; | 783 uint16_t lookup_count = 0; |
| 781 if (!subtable.ReadU16(&lookup_count)) { | 784 if (!subtable.ReadU16(&lookup_count)) { |
| 782 return OTS_FAILURE(); | 785 return OTS_FAILURE_MSG("Failed to read lookup count in chain rule subtable")
; |
| 783 } | 786 } |
| 784 for (unsigned i = 0; i < lookup_count; ++i) { | 787 for (unsigned i = 0; i < lookup_count; ++i) { |
| 785 if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) { | 788 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { |
| 786 return OTS_FAILURE(); | 789 return OTS_FAILURE_MSG("Failed to parse lookup record %d in chain rule sub
table", i); |
| 787 } | 790 } |
| 788 } | 791 } |
| 789 | 792 |
| 790 return true; | 793 return true; |
| 791 } | 794 } |
| 792 | 795 |
| 793 bool ParseChainRuleSetTable(const uint8_t *data, const size_t length, | 796 bool ParseChainRuleSetTable(const ots::OpenTypeFile *file, |
| 797 const uint8_t *data, const size_t length, |
| 794 const uint16_t num_glyphs, | 798 const uint16_t num_glyphs, |
| 795 const uint16_t num_lookups) { | 799 const uint16_t num_lookups) { |
| 796 ots::Buffer subtable(data, length); | 800 ots::Buffer subtable(data, length); |
| 797 | 801 |
| 798 uint16_t chain_rule_count = 0; | 802 uint16_t chain_rule_count = 0; |
| 799 if (!subtable.ReadU16(&chain_rule_count)) { | 803 if (!subtable.ReadU16(&chain_rule_count)) { |
| 800 return OTS_FAILURE(); | 804 return OTS_FAILURE_MSG("Failed to read rule count in chain rule set"); |
| 801 } | 805 } |
| 802 const unsigned chain_rule_end = | 806 const unsigned chain_rule_end = |
| 803 2 * static_cast<unsigned>(chain_rule_count) + 2; | 807 2 * static_cast<unsigned>(chain_rule_count) + 2; |
| 804 if (chain_rule_end > std::numeric_limits<uint16_t>::max()) { | 808 if (chain_rule_end > std::numeric_limits<uint16_t>::max()) { |
| 805 return OTS_FAILURE(); | 809 return OTS_FAILURE_MSG("Bad end of chain rule %d in chain rule set", chain_r
ule_end); |
| 806 } | 810 } |
| 807 for (unsigned i = 0; i < chain_rule_count; ++i) { | 811 for (unsigned i = 0; i < chain_rule_count; ++i) { |
| 808 uint16_t offset_chain_rule = 0; | 812 uint16_t offset_chain_rule = 0; |
| 809 if (!subtable.ReadU16(&offset_chain_rule)) { | 813 if (!subtable.ReadU16(&offset_chain_rule)) { |
| 810 return OTS_FAILURE(); | 814 return OTS_FAILURE_MSG("Failed to read chain rule offset %d in chain rule
set", i); |
| 811 } | 815 } |
| 812 if (offset_chain_rule < chain_rule_end || offset_chain_rule >= length) { | 816 if (offset_chain_rule < chain_rule_end || offset_chain_rule >= length) { |
| 813 return OTS_FAILURE(); | 817 return OTS_FAILURE_MSG("Bad chain rule offset %d for chain rule %d in chai
n rule set", offset_chain_rule, i); |
| 814 } | 818 } |
| 815 if (!ParseChainRuleSubtable(data + offset_chain_rule, | 819 if (!ParseChainRuleSubtable(file, data + offset_chain_rule, |
| 816 length - offset_chain_rule, | 820 length - offset_chain_rule, |
| 817 num_glyphs, num_lookups)) { | 821 num_glyphs, num_lookups)) { |
| 818 return OTS_FAILURE(); | 822 return OTS_FAILURE_MSG("Failed to parse chain rule %d in chain rule set",
i); |
| 819 } | 823 } |
| 820 } | 824 } |
| 821 | 825 |
| 822 return true; | 826 return true; |
| 823 } | 827 } |
| 824 | 828 |
| 825 bool ParseChainContextFormat1(const uint8_t *data, const size_t length, | 829 bool ParseChainContextFormat1(const ots::OpenTypeFile *file, |
| 830 const uint8_t *data, const size_t length, |
| 826 const uint16_t num_glyphs, | 831 const uint16_t num_glyphs, |
| 827 const uint16_t num_lookups) { | 832 const uint16_t num_lookups) { |
| 828 ots::Buffer subtable(data, length); | 833 ots::Buffer subtable(data, length); |
| 829 | 834 |
| 830 uint16_t offset_coverage = 0; | 835 uint16_t offset_coverage = 0; |
| 831 uint16_t chain_rule_set_count = 0; | 836 uint16_t chain_rule_set_count = 0; |
| 832 // Skip format field. | 837 // Skip format field. |
| 833 if (!subtable.Skip(2) || | 838 if (!subtable.Skip(2) || |
| 834 !subtable.ReadU16(&offset_coverage) || | 839 !subtable.ReadU16(&offset_coverage) || |
| 835 !subtable.ReadU16(&chain_rule_set_count)) { | 840 !subtable.ReadU16(&chain_rule_set_count)) { |
| 836 return OTS_FAILURE(); | 841 return OTS_FAILURE_MSG("Failed to read header of chain context format 1"); |
| 837 } | 842 } |
| 838 | 843 |
| 839 const unsigned chain_rule_set_end = | 844 const unsigned chain_rule_set_end = |
| 840 2 * static_cast<unsigned>(chain_rule_set_count) + 6; | 845 2 * static_cast<unsigned>(chain_rule_set_count) + 6; |
| 841 if (chain_rule_set_end > std::numeric_limits<uint16_t>::max()) { | 846 if (chain_rule_set_end > std::numeric_limits<uint16_t>::max()) { |
| 842 return OTS_FAILURE(); | 847 return OTS_FAILURE_MSG("Bad chain rule end %d in chain context format 1", ch
ain_rule_set_end); |
| 843 } | 848 } |
| 844 if (offset_coverage < chain_rule_set_end || offset_coverage >= length) { | 849 if (offset_coverage < chain_rule_set_end || offset_coverage >= length) { |
| 845 return OTS_FAILURE(); | 850 return OTS_FAILURE_MSG("Bad coverage offset %d in chain context format 1", c
hain_rule_set_end); |
| 846 } | 851 } |
| 847 if (!ots::ParseCoverageTable(data + offset_coverage, | 852 if (!ots::ParseCoverageTable(file, data + offset_coverage, |
| 848 length - offset_coverage, num_glyphs)) { | 853 length - offset_coverage, num_glyphs)) { |
| 849 return OTS_FAILURE(); | 854 return OTS_FAILURE_MSG("Failed to parse coverage table for chain context for
mat 1"); |
| 850 } | 855 } |
| 851 | 856 |
| 852 for (unsigned i = 0; i < chain_rule_set_count; ++i) { | 857 for (unsigned i = 0; i < chain_rule_set_count; ++i) { |
| 853 uint16_t offset_chain_rule_set = 0; | 858 uint16_t offset_chain_rule_set = 0; |
| 854 if (!subtable.ReadU16(&offset_chain_rule_set)) { | 859 if (!subtable.ReadU16(&offset_chain_rule_set)) { |
| 855 return OTS_FAILURE(); | 860 return OTS_FAILURE_MSG("Failed to read chain rule offset %d in chain conte
xt format 1", i); |
| 856 } | 861 } |
| 857 if (offset_chain_rule_set < chain_rule_set_end || | 862 if (offset_chain_rule_set < chain_rule_set_end || |
| 858 offset_chain_rule_set >= length) { | 863 offset_chain_rule_set >= length) { |
| 859 return OTS_FAILURE(); | 864 return OTS_FAILURE_MSG("Bad chain rule set offset %d for chain rule set %d
in chain context format 1", offset_chain_rule_set, i); |
| 860 } | 865 } |
| 861 if (!ParseChainRuleSetTable(data + offset_chain_rule_set, | 866 if (!ParseChainRuleSetTable(file, data + offset_chain_rule_set, |
| 862 length - offset_chain_rule_set, | 867 length - offset_chain_rule_set, |
| 863 num_glyphs, num_lookups)) { | 868 num_glyphs, num_lookups)) { |
| 864 return OTS_FAILURE(); | 869 return OTS_FAILURE_MSG("Failed to parse chain rule set %d in chain context
format 1", i); |
| 865 } | 870 } |
| 866 } | 871 } |
| 867 | 872 |
| 868 return true; | 873 return true; |
| 869 } | 874 } |
| 870 | 875 |
| 871 bool ParseChainClassRuleSubtable(const uint8_t *data, const size_t length, | 876 bool ParseChainClassRuleSubtable(const ots::OpenTypeFile *file, |
| 877 const uint8_t *data, const size_t length, |
| 872 const uint16_t num_glyphs, | 878 const uint16_t num_glyphs, |
| 873 const uint16_t num_lookups) { | 879 const uint16_t num_lookups) { |
| 874 ots::Buffer subtable(data, length); | 880 ots::Buffer subtable(data, length); |
| 875 | 881 |
| 876 // In this subtable, we don't check the value of classes for now since | 882 // In this subtable, we don't check the value of classes for now since |
| 877 // these could take arbitrary values. | 883 // these could take arbitrary values. |
| 878 | 884 |
| 879 uint16_t backtrack_count = 0; | 885 uint16_t backtrack_count = 0; |
| 880 if (!subtable.ReadU16(&backtrack_count)) { | 886 if (!subtable.ReadU16(&backtrack_count)) { |
| 881 return OTS_FAILURE(); | 887 return OTS_FAILURE_MSG("Failed to read backtrack count in chain class rule s
ubtable"); |
| 882 } | 888 } |
| 883 if (backtrack_count >= num_glyphs) { | 889 if (backtrack_count >= num_glyphs) { |
| 884 return OTS_FAILURE(); | 890 return OTS_FAILURE_MSG("Bad backtrack count %d in chain class rule subtable"
, backtrack_count); |
| 885 } | 891 } |
| 886 if (!subtable.Skip(2 * backtrack_count)) { | 892 if (!subtable.Skip(2 * backtrack_count)) { |
| 887 return OTS_FAILURE(); | 893 return OTS_FAILURE_MSG("Failed to skip backtrack offsets in chain class rule
subtable"); |
| 888 } | 894 } |
| 889 | 895 |
| 890 uint16_t input_count = 0; | 896 uint16_t input_count = 0; |
| 891 if (!subtable.ReadU16(&input_count)) { | 897 if (!subtable.ReadU16(&input_count)) { |
| 892 return OTS_FAILURE(); | 898 return OTS_FAILURE_MSG("Failed to read input count in chain class rule subta
ble"); |
| 893 } | 899 } |
| 894 if (input_count == 0 || input_count >= num_glyphs) { | 900 if (input_count == 0 || input_count >= num_glyphs) { |
| 895 return OTS_FAILURE(); | 901 return OTS_FAILURE_MSG("Bad input count %d in chain class rule subtable", in
put_count); |
| 896 } | 902 } |
| 897 if (!subtable.Skip(2 * (input_count - 1))) { | 903 if (!subtable.Skip(2 * (input_count - 1))) { |
| 898 return OTS_FAILURE(); | 904 return OTS_FAILURE_MSG("Failed to skip input offsets in chain class rule sub
table"); |
| 899 } | 905 } |
| 900 | 906 |
| 901 uint16_t lookahead_count = 0; | 907 uint16_t lookahead_count = 0; |
| 902 if (!subtable.ReadU16(&lookahead_count)) { | 908 if (!subtable.ReadU16(&lookahead_count)) { |
| 903 return OTS_FAILURE(); | 909 return OTS_FAILURE_MSG("Failed to read lookahead count in chain class rule s
ubtable"); |
| 904 } | 910 } |
| 905 if (lookahead_count >= num_glyphs) { | 911 if (lookahead_count >= num_glyphs) { |
| 906 return OTS_FAILURE(); | 912 return OTS_FAILURE_MSG("Bad lookahead count %d in chain class rule subtable"
, lookahead_count); |
| 907 } | 913 } |
| 908 if (!subtable.Skip(2 * lookahead_count)) { | 914 if (!subtable.Skip(2 * lookahead_count)) { |
| 909 return OTS_FAILURE(); | 915 return OTS_FAILURE_MSG("Failed to skip lookahead offsets in chain class rule
subtable"); |
| 910 } | 916 } |
| 911 | 917 |
| 912 uint16_t lookup_count = 0; | 918 uint16_t lookup_count = 0; |
| 913 if (!subtable.ReadU16(&lookup_count)) { | 919 if (!subtable.ReadU16(&lookup_count)) { |
| 914 return OTS_FAILURE(); | 920 return OTS_FAILURE_MSG("Failed to read lookup count in chain class rule subt
able"); |
| 915 } | 921 } |
| 916 for (unsigned i = 0; i < lookup_count; ++i) { | 922 for (unsigned i = 0; i < lookup_count; ++i) { |
| 917 if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) { | 923 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { |
| 918 return OTS_FAILURE(); | 924 return OTS_FAILURE_MSG("Failed to parse lookup record %d in chain class ru
le subtable", i); |
| 919 } | 925 } |
| 920 } | 926 } |
| 921 | 927 |
| 922 return true; | 928 return true; |
| 923 } | 929 } |
| 924 | 930 |
| 925 bool ParseChainClassSetTable(const uint8_t *data, const size_t length, | 931 bool ParseChainClassSetTable(const ots::OpenTypeFile *file, |
| 932 const uint8_t *data, const size_t length, |
| 926 const uint16_t num_glyphs, | 933 const uint16_t num_glyphs, |
| 927 const uint16_t num_lookups) { | 934 const uint16_t num_lookups) { |
| 928 ots::Buffer subtable(data, length); | 935 ots::Buffer subtable(data, length); |
| 929 | 936 |
| 930 uint16_t chain_class_rule_count = 0; | 937 uint16_t chain_class_rule_count = 0; |
| 931 if (!subtable.ReadU16(&chain_class_rule_count)) { | 938 if (!subtable.ReadU16(&chain_class_rule_count)) { |
| 932 return OTS_FAILURE(); | 939 return OTS_FAILURE_MSG("Failed to read rule count in chain class set"); |
| 933 } | 940 } |
| 934 const unsigned chain_class_rule_end = | 941 const unsigned chain_class_rule_end = |
| 935 2 * static_cast<unsigned>(chain_class_rule_count) + 2; | 942 2 * static_cast<unsigned>(chain_class_rule_count) + 2; |
| 936 if (chain_class_rule_end > std::numeric_limits<uint16_t>::max()) { | 943 if (chain_class_rule_end > std::numeric_limits<uint16_t>::max()) { |
| 937 return OTS_FAILURE(); | 944 return OTS_FAILURE_MSG("Bad end of chain class set %d in chain class set", c
hain_class_rule_end); |
| 938 } | 945 } |
| 939 for (unsigned i = 0; i < chain_class_rule_count; ++i) { | 946 for (unsigned i = 0; i < chain_class_rule_count; ++i) { |
| 940 uint16_t offset_chain_class_rule = 0; | 947 uint16_t offset_chain_class_rule = 0; |
| 941 if (!subtable.ReadU16(&offset_chain_class_rule)) { | 948 if (!subtable.ReadU16(&offset_chain_class_rule)) { |
| 942 return OTS_FAILURE(); | 949 return OTS_FAILURE_MSG("Failed to read chain class rule offset %d in chain
class set", i); |
| 943 } | 950 } |
| 944 if (offset_chain_class_rule < chain_class_rule_end || | 951 if (offset_chain_class_rule < chain_class_rule_end || |
| 945 offset_chain_class_rule >= length) { | 952 offset_chain_class_rule >= length) { |
| 946 return OTS_FAILURE(); | 953 return OTS_FAILURE_MSG("Bad chain class rule offset %d for chain class %d
in chain class set", offset_chain_class_rule, i); |
| 947 } | 954 } |
| 948 if (!ParseChainClassRuleSubtable(data + offset_chain_class_rule, | 955 if (!ParseChainClassRuleSubtable(file, data + offset_chain_class_rule, |
| 949 length - offset_chain_class_rule, | 956 length - offset_chain_class_rule, |
| 950 num_glyphs, num_lookups)) { | 957 num_glyphs, num_lookups)) { |
| 951 return OTS_FAILURE(); | 958 return OTS_FAILURE_MSG("Failed to parse chain class rule %d in chain class
set", i); |
| 952 } | 959 } |
| 953 } | 960 } |
| 954 | 961 |
| 955 return true; | 962 return true; |
| 956 } | 963 } |
| 957 | 964 |
| 958 bool ParseChainContextFormat2(const uint8_t *data, const size_t length, | 965 bool ParseChainContextFormat2(const ots::OpenTypeFile *file, |
| 966 const uint8_t *data, const size_t length, |
| 959 const uint16_t num_glyphs, | 967 const uint16_t num_glyphs, |
| 960 const uint16_t num_lookups) { | 968 const uint16_t num_lookups) { |
| 961 ots::Buffer subtable(data, length); | 969 ots::Buffer subtable(data, length); |
| 962 | 970 |
| 963 uint16_t offset_coverage = 0; | 971 uint16_t offset_coverage = 0; |
| 964 uint16_t offset_backtrack_class_def = 0; | 972 uint16_t offset_backtrack_class_def = 0; |
| 965 uint16_t offset_input_class_def = 0; | 973 uint16_t offset_input_class_def = 0; |
| 966 uint16_t offset_lookahead_class_def = 0; | 974 uint16_t offset_lookahead_class_def = 0; |
| 967 uint16_t chain_class_set_count = 0; | 975 uint16_t chain_class_set_count = 0; |
| 968 // Skip format field. | 976 // Skip format field. |
| 969 if (!subtable.Skip(2) || | 977 if (!subtable.Skip(2) || |
| 970 !subtable.ReadU16(&offset_coverage) || | 978 !subtable.ReadU16(&offset_coverage) || |
| 971 !subtable.ReadU16(&offset_backtrack_class_def) || | 979 !subtable.ReadU16(&offset_backtrack_class_def) || |
| 972 !subtable.ReadU16(&offset_input_class_def) || | 980 !subtable.ReadU16(&offset_input_class_def) || |
| 973 !subtable.ReadU16(&offset_lookahead_class_def) || | 981 !subtable.ReadU16(&offset_lookahead_class_def) || |
| 974 !subtable.ReadU16(&chain_class_set_count)) { | 982 !subtable.ReadU16(&chain_class_set_count)) { |
| 975 return OTS_FAILURE(); | 983 return OTS_FAILURE_MSG("Failed to read header of chain context format 2"); |
| 976 } | 984 } |
| 977 | 985 |
| 978 const unsigned chain_class_set_end = | 986 const unsigned chain_class_set_end = |
| 979 2 * static_cast<unsigned>(chain_class_set_count) + 12; | 987 2 * static_cast<unsigned>(chain_class_set_count) + 12; |
| 980 if (chain_class_set_end > std::numeric_limits<uint16_t>::max()) { | 988 if (chain_class_set_end > std::numeric_limits<uint16_t>::max()) { |
| 981 return OTS_FAILURE(); | 989 return OTS_FAILURE_MSG("Bad chain class set end %d in chain context format 2
", chain_class_set_end); |
| 982 } | 990 } |
| 983 if (offset_coverage < chain_class_set_end || offset_coverage >= length) { | 991 if (offset_coverage < chain_class_set_end || offset_coverage >= length) { |
| 984 return OTS_FAILURE(); | 992 return OTS_FAILURE_MSG("Bad coverage offset %d in chain context format 2", o
ffset_coverage); |
| 985 } | 993 } |
| 986 if (!ots::ParseCoverageTable(data + offset_coverage, | 994 if (!ots::ParseCoverageTable(file, data + offset_coverage, |
| 987 length - offset_coverage, num_glyphs)) { | 995 length - offset_coverage, num_glyphs)) { |
| 988 return OTS_FAILURE(); | 996 return OTS_FAILURE_MSG("Failed to parse coverage table in chain context form
at 2"); |
| 989 } | 997 } |
| 990 | 998 |
| 991 // Classes for backtrack/lookahead sequences might not be defined. | 999 // Classes for backtrack/lookahead sequences might not be defined. |
| 992 if (offset_backtrack_class_def) { | 1000 if (offset_backtrack_class_def) { |
| 993 if (offset_backtrack_class_def < chain_class_set_end || | 1001 if (offset_backtrack_class_def < chain_class_set_end || |
| 994 offset_backtrack_class_def >= length) { | 1002 offset_backtrack_class_def >= length) { |
| 995 return OTS_FAILURE(); | 1003 return OTS_FAILURE_MSG("Bad backtrack class offset %d in chain context for
mat 2", offset_backtrack_class_def); |
| 996 } | 1004 } |
| 997 if (!ots::ParseClassDefTable(data + offset_backtrack_class_def, | 1005 if (!ots::ParseClassDefTable(file, data + offset_backtrack_class_def, |
| 998 length - offset_backtrack_class_def, | 1006 length - offset_backtrack_class_def, |
| 999 num_glyphs, kMaxClassDefValue)) { | 1007 num_glyphs, kMaxClassDefValue)) { |
| 1000 return OTS_FAILURE(); | 1008 return OTS_FAILURE_MSG("Failed to parse backtrack class defn table in chai
n context format 2"); |
| 1001 } | 1009 } |
| 1002 } | 1010 } |
| 1003 | 1011 |
| 1004 if (offset_input_class_def < chain_class_set_end || | 1012 if (offset_input_class_def < chain_class_set_end || |
| 1005 offset_input_class_def >= length) { | 1013 offset_input_class_def >= length) { |
| 1006 return OTS_FAILURE(); | 1014 return OTS_FAILURE_MSG("Bad input class defn offset %d in chain context form
at 2", offset_input_class_def); |
| 1007 } | 1015 } |
| 1008 if (!ots::ParseClassDefTable(data + offset_input_class_def, | 1016 if (!ots::ParseClassDefTable(file, data + offset_input_class_def, |
| 1009 length - offset_input_class_def, | 1017 length - offset_input_class_def, |
| 1010 num_glyphs, kMaxClassDefValue)) { | 1018 num_glyphs, kMaxClassDefValue)) { |
| 1011 return OTS_FAILURE(); | 1019 return OTS_FAILURE_MSG("Failed to parse input class defn in chain context fo
rmat 2"); |
| 1012 } | 1020 } |
| 1013 | 1021 |
| 1014 if (offset_lookahead_class_def) { | 1022 if (offset_lookahead_class_def) { |
| 1015 if (offset_lookahead_class_def < chain_class_set_end || | 1023 if (offset_lookahead_class_def < chain_class_set_end || |
| 1016 offset_lookahead_class_def >= length) { | 1024 offset_lookahead_class_def >= length) { |
| 1017 return OTS_FAILURE(); | 1025 return OTS_FAILURE_MSG("Bad lookahead class defn offset %d in chain contex
t format 2", offset_lookahead_class_def); |
| 1018 } | 1026 } |
| 1019 if (!ots::ParseClassDefTable(data + offset_lookahead_class_def, | 1027 if (!ots::ParseClassDefTable(file, data + offset_lookahead_class_def, |
| 1020 length - offset_lookahead_class_def, | 1028 length - offset_lookahead_class_def, |
| 1021 num_glyphs, kMaxClassDefValue)) { | 1029 num_glyphs, kMaxClassDefValue)) { |
| 1022 return OTS_FAILURE(); | 1030 return OTS_FAILURE_MSG("Failed to parse lookahead class defn in chain cont
ext format 2"); |
| 1023 } | 1031 } |
| 1024 } | 1032 } |
| 1025 | 1033 |
| 1026 for (unsigned i = 0; i < chain_class_set_count; ++i) { | 1034 for (unsigned i = 0; i < chain_class_set_count; ++i) { |
| 1027 uint16_t offset_chain_class_set = 0; | 1035 uint16_t offset_chain_class_set = 0; |
| 1028 if (!subtable.ReadU16(&offset_chain_class_set)) { | 1036 if (!subtable.ReadU16(&offset_chain_class_set)) { |
| 1029 return OTS_FAILURE(); | 1037 return OTS_FAILURE_MSG("Failed to read chain class set offset %d", i); |
| 1030 } | 1038 } |
| 1031 // |offset_chain_class_set| could be NULL. | 1039 // |offset_chain_class_set| could be NULL. |
| 1032 if (offset_chain_class_set) { | 1040 if (offset_chain_class_set) { |
| 1033 if (offset_chain_class_set < chain_class_set_end || | 1041 if (offset_chain_class_set < chain_class_set_end || |
| 1034 offset_chain_class_set >= length) { | 1042 offset_chain_class_set >= length) { |
| 1035 return OTS_FAILURE(); | 1043 return OTS_FAILURE_MSG("Bad chain set class offset %d for chain set %d i
n chain context format 2", offset_chain_class_set, i); |
| 1036 } | 1044 } |
| 1037 if (!ParseChainClassSetTable(data + offset_chain_class_set, | 1045 if (!ParseChainClassSetTable(file, data + offset_chain_class_set, |
| 1038 length - offset_chain_class_set, | 1046 length - offset_chain_class_set, |
| 1039 num_glyphs, num_lookups)) { | 1047 num_glyphs, num_lookups)) { |
| 1040 return OTS_FAILURE(); | 1048 return OTS_FAILURE_MSG("Failed to parse chain class set table %d in chai
n context format 2", i); |
| 1041 } | 1049 } |
| 1042 } | 1050 } |
| 1043 } | 1051 } |
| 1044 | 1052 |
| 1045 return true; | 1053 return true; |
| 1046 } | 1054 } |
| 1047 | 1055 |
| 1048 bool ParseChainContextFormat3(const uint8_t *data, const size_t length, | 1056 bool ParseChainContextFormat3(const ots::OpenTypeFile *file, |
| 1057 const uint8_t *data, const size_t length, |
| 1049 const uint16_t num_glyphs, | 1058 const uint16_t num_glyphs, |
| 1050 const uint16_t num_lookups) { | 1059 const uint16_t num_lookups) { |
| 1051 ots::Buffer subtable(data, length); | 1060 ots::Buffer subtable(data, length); |
| 1052 | 1061 |
| 1053 uint16_t backtrack_count = 0; | 1062 uint16_t backtrack_count = 0; |
| 1054 // Skip format field. | 1063 // Skip format field. |
| 1055 if (!subtable.Skip(2) || | 1064 if (!subtable.Skip(2) || |
| 1056 !subtable.ReadU16(&backtrack_count)) { | 1065 !subtable.ReadU16(&backtrack_count)) { |
| 1057 return OTS_FAILURE(); | 1066 return OTS_FAILURE_MSG("Failed to read backtrack count in chain context form
at 3"); |
| 1058 } | 1067 } |
| 1059 | 1068 |
| 1060 if (backtrack_count >= num_glyphs) { | 1069 if (backtrack_count >= num_glyphs) { |
| 1061 return OTS_FAILURE(); | 1070 return OTS_FAILURE_MSG("Bad backtrack count %d in chain context format 3", b
acktrack_count); |
| 1062 } | 1071 } |
| 1063 std::vector<uint16_t> offsets_backtrack; | 1072 std::vector<uint16_t> offsets_backtrack; |
| 1064 offsets_backtrack.reserve(backtrack_count); | 1073 offsets_backtrack.reserve(backtrack_count); |
| 1065 for (unsigned i = 0; i < backtrack_count; ++i) { | 1074 for (unsigned i = 0; i < backtrack_count; ++i) { |
| 1066 uint16_t offset = 0; | 1075 uint16_t offset = 0; |
| 1067 if (!subtable.ReadU16(&offset)) { | 1076 if (!subtable.ReadU16(&offset)) { |
| 1068 return OTS_FAILURE(); | 1077 return OTS_FAILURE_MSG("Failed to read backtrack offset %d in chain contex
t format 3", i); |
| 1069 } | 1078 } |
| 1070 offsets_backtrack.push_back(offset); | 1079 offsets_backtrack.push_back(offset); |
| 1071 } | 1080 } |
| 1072 if (offsets_backtrack.size() != backtrack_count) { | 1081 if (offsets_backtrack.size() != backtrack_count) { |
| 1073 return OTS_FAILURE(); | 1082 return OTS_FAILURE_MSG("Bad backtrack offsets size %ld in chain context form
at 3", offsets_backtrack.size()); |
| 1074 } | 1083 } |
| 1075 | 1084 |
| 1076 uint16_t input_count = 0; | 1085 uint16_t input_count = 0; |
| 1077 if (!subtable.ReadU16(&input_count)) { | 1086 if (!subtable.ReadU16(&input_count)) { |
| 1078 return OTS_FAILURE(); | 1087 return OTS_FAILURE_MSG("Failed to read input count in chain context format 3
"); |
| 1079 } | 1088 } |
| 1080 if (input_count >= num_glyphs) { | 1089 if (input_count >= num_glyphs) { |
| 1081 return OTS_FAILURE(); | 1090 return OTS_FAILURE_MSG("Bad input count %d in chain context format 3", input
_count); |
| 1082 } | 1091 } |
| 1083 std::vector<uint16_t> offsets_input; | 1092 std::vector<uint16_t> offsets_input; |
| 1084 offsets_input.reserve(input_count); | 1093 offsets_input.reserve(input_count); |
| 1085 for (unsigned i = 0; i < input_count; ++i) { | 1094 for (unsigned i = 0; i < input_count; ++i) { |
| 1086 uint16_t offset = 0; | 1095 uint16_t offset = 0; |
| 1087 if (!subtable.ReadU16(&offset)) { | 1096 if (!subtable.ReadU16(&offset)) { |
| 1088 return OTS_FAILURE(); | 1097 return OTS_FAILURE_MSG("Failed to read input offset %d in chain context fo
rmat 3", i); |
| 1089 } | 1098 } |
| 1090 offsets_input.push_back(offset); | 1099 offsets_input.push_back(offset); |
| 1091 } | 1100 } |
| 1092 if (offsets_input.size() != input_count) { | 1101 if (offsets_input.size() != input_count) { |
| 1093 return OTS_FAILURE(); | 1102 return OTS_FAILURE_MSG("Bad input offsets size %ld in chain context format 3
", offsets_input.size()); |
| 1094 } | 1103 } |
| 1095 | 1104 |
| 1096 uint16_t lookahead_count = 0; | 1105 uint16_t lookahead_count = 0; |
| 1097 if (!subtable.ReadU16(&lookahead_count)) { | 1106 if (!subtable.ReadU16(&lookahead_count)) { |
| 1098 return OTS_FAILURE(); | 1107 return OTS_FAILURE_MSG("Failed ot read lookahead count in chain context form
at 3"); |
| 1099 } | 1108 } |
| 1100 if (lookahead_count >= num_glyphs) { | 1109 if (lookahead_count >= num_glyphs) { |
| 1101 return OTS_FAILURE(); | 1110 return OTS_FAILURE_MSG("Bad lookahead count %d in chain context format 3", l
ookahead_count); |
| 1102 } | 1111 } |
| 1103 std::vector<uint16_t> offsets_lookahead; | 1112 std::vector<uint16_t> offsets_lookahead; |
| 1104 offsets_lookahead.reserve(lookahead_count); | 1113 offsets_lookahead.reserve(lookahead_count); |
| 1105 for (unsigned i = 0; i < lookahead_count; ++i) { | 1114 for (unsigned i = 0; i < lookahead_count; ++i) { |
| 1106 uint16_t offset = 0; | 1115 uint16_t offset = 0; |
| 1107 if (!subtable.ReadU16(&offset)) { | 1116 if (!subtable.ReadU16(&offset)) { |
| 1108 return OTS_FAILURE(); | 1117 return OTS_FAILURE_MSG("Failed to read lookahead offset %d in chain contex
t format 3", i); |
| 1109 } | 1118 } |
| 1110 offsets_lookahead.push_back(offset); | 1119 offsets_lookahead.push_back(offset); |
| 1111 } | 1120 } |
| 1112 if (offsets_lookahead.size() != lookahead_count) { | 1121 if (offsets_lookahead.size() != lookahead_count) { |
| 1113 return OTS_FAILURE(); | 1122 return OTS_FAILURE_MSG("Bad lookahead offsets size %ld in chain context form
at 3", offsets_lookahead.size()); |
| 1114 } | 1123 } |
| 1115 | 1124 |
| 1116 uint16_t lookup_count = 0; | 1125 uint16_t lookup_count = 0; |
| 1117 if (!subtable.ReadU16(&lookup_count)) { | 1126 if (!subtable.ReadU16(&lookup_count)) { |
| 1118 return OTS_FAILURE(); | 1127 return OTS_FAILURE_MSG("Failed to read lookup count in chain context format
3"); |
| 1119 } | 1128 } |
| 1120 for (unsigned i = 0; i < lookup_count; ++i) { | 1129 for (unsigned i = 0; i < lookup_count; ++i) { |
| 1121 if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) { | 1130 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { |
| 1122 return OTS_FAILURE(); | 1131 return OTS_FAILURE_MSG("Failed to parse lookup %d in chain context format
3", i); |
| 1123 } | 1132 } |
| 1124 } | 1133 } |
| 1125 | 1134 |
| 1126 const unsigned lookup_record_end = | 1135 const unsigned lookup_record_end = |
| 1127 2 * (static_cast<unsigned>(backtrack_count) + | 1136 2 * (static_cast<unsigned>(backtrack_count) + |
| 1128 static_cast<unsigned>(input_count) + | 1137 static_cast<unsigned>(input_count) + |
| 1129 static_cast<unsigned>(lookahead_count)) + | 1138 static_cast<unsigned>(lookahead_count)) + |
| 1130 4 * static_cast<unsigned>(lookup_count) + 10; | 1139 4 * static_cast<unsigned>(lookup_count) + 10; |
| 1131 if (lookup_record_end > std::numeric_limits<uint16_t>::max()) { | 1140 if (lookup_record_end > std::numeric_limits<uint16_t>::max()) { |
| 1132 return OTS_FAILURE(); | 1141 return OTS_FAILURE_MSG("Bad end of lookup record %d in chain context format
3", lookup_record_end); |
| 1133 } | 1142 } |
| 1134 for (unsigned i = 0; i < backtrack_count; ++i) { | 1143 for (unsigned i = 0; i < backtrack_count; ++i) { |
| 1135 if (offsets_backtrack[i] < lookup_record_end || | 1144 if (offsets_backtrack[i] < lookup_record_end || |
| 1136 offsets_backtrack[i] >= length) { | 1145 offsets_backtrack[i] >= length) { |
| 1137 return OTS_FAILURE(); | 1146 return OTS_FAILURE_MSG("Bad backtrack offset of %d for backtrack %d in cha
in context format 3", offsets_backtrack[i], i); |
| 1138 } | 1147 } |
| 1139 if (!ots::ParseCoverageTable(data + offsets_backtrack[i], | 1148 if (!ots::ParseCoverageTable(file, data + offsets_backtrack[i], |
| 1140 length - offsets_backtrack[i], num_glyphs)) { | 1149 length - offsets_backtrack[i], num_glyphs)) { |
| 1141 return OTS_FAILURE(); | 1150 return OTS_FAILURE_MSG("Failed to parse backtrack coverage %d in chain con
text format 3", i); |
| 1142 } | 1151 } |
| 1143 } | 1152 } |
| 1144 for (unsigned i = 0; i < input_count; ++i) { | 1153 for (unsigned i = 0; i < input_count; ++i) { |
| 1145 if (offsets_input[i] < lookup_record_end || offsets_input[i] >= length) { | 1154 if (offsets_input[i] < lookup_record_end || offsets_input[i] >= length) { |
| 1146 return OTS_FAILURE(); | 1155 return OTS_FAILURE_MSG("Bad input offset %d for input %d in chain context
format 3", offsets_input[i], i); |
| 1147 } | 1156 } |
| 1148 if (!ots::ParseCoverageTable(data + offsets_input[i], | 1157 if (!ots::ParseCoverageTable(file, data + offsets_input[i], |
| 1149 length - offsets_input[i], num_glyphs)) { | 1158 length - offsets_input[i], num_glyphs)) { |
| 1150 return OTS_FAILURE(); | 1159 return OTS_FAILURE_MSG("Failed to parse input coverage table %d in chain c
ontext format 3", i); |
| 1151 } | 1160 } |
| 1152 } | 1161 } |
| 1153 for (unsigned i = 0; i < lookahead_count; ++i) { | 1162 for (unsigned i = 0; i < lookahead_count; ++i) { |
| 1154 if (offsets_lookahead[i] < lookup_record_end || | 1163 if (offsets_lookahead[i] < lookup_record_end || |
| 1155 offsets_lookahead[i] >= length) { | 1164 offsets_lookahead[i] >= length) { |
| 1156 return OTS_FAILURE(); | 1165 return OTS_FAILURE_MSG("Bad lookadhead offset %d for lookahead %d in chain
context format 3", offsets_lookahead[i], i); |
| 1157 } | 1166 } |
| 1158 if (!ots::ParseCoverageTable(data + offsets_lookahead[i], | 1167 if (!ots::ParseCoverageTable(file, data + offsets_lookahead[i], |
| 1159 length - offsets_lookahead[i], num_glyphs)) { | 1168 length - offsets_lookahead[i], num_glyphs)) { |
| 1160 return OTS_FAILURE(); | 1169 return OTS_FAILURE_MSG("Failed to parse lookahead coverage table %d in cha
in context format 3", i); |
| 1161 } | 1170 } |
| 1162 } | 1171 } |
| 1163 | 1172 |
| 1164 return true; | 1173 return true; |
| 1165 } | 1174 } |
| 1166 | 1175 |
| 1167 } // namespace | 1176 } // namespace |
| 1168 | 1177 |
| 1169 namespace ots { | 1178 namespace ots { |
| 1170 | 1179 |
| 1171 bool LookupSubtableParser::Parse(const OpenTypeFile *file, const uint8_t *data, | 1180 bool LookupSubtableParser::Parse(const OpenTypeFile *file, const uint8_t *data, |
| 1172 const size_t length, | 1181 const size_t length, |
| 1173 const uint16_t lookup_type) const { | 1182 const uint16_t lookup_type) const { |
| 1174 for (unsigned i = 0; i < num_types; ++i) { | 1183 for (unsigned i = 0; i < num_types; ++i) { |
| 1175 if (parsers[i].type == lookup_type && parsers[i].parse) { | 1184 if (parsers[i].type == lookup_type && parsers[i].parse) { |
| 1176 if (!parsers[i].parse(file, data, length)) { | 1185 if (!parsers[i].parse(file, data, length)) { |
| 1177 return OTS_FAILURE(); | 1186 return OTS_FAILURE_MSG("Failed to parse lookup subtable %d", i); |
| 1178 } | 1187 } |
| 1179 return true; | 1188 return true; |
| 1180 } | 1189 } |
| 1181 } | 1190 } |
| 1182 return OTS_FAILURE(); | 1191 return OTS_FAILURE_MSG("No lookup subtables to parse"); |
| 1183 } | 1192 } |
| 1184 | 1193 |
| 1185 // Parsing ScriptListTable requires number of features so we need to | 1194 // Parsing ScriptListTable requires number of features so we need to |
| 1186 // parse FeatureListTable before calling this function. | 1195 // parse FeatureListTable before calling this function. |
| 1187 bool ParseScriptListTable(const uint8_t *data, const size_t length, | 1196 bool ParseScriptListTable(const ots::OpenTypeFile *file, |
| 1197 const uint8_t *data, const size_t length, |
| 1188 const uint16_t num_features) { | 1198 const uint16_t num_features) { |
| 1189 Buffer subtable(data, length); | 1199 Buffer subtable(data, length); |
| 1190 | 1200 |
| 1191 uint16_t script_count = 0; | 1201 uint16_t script_count = 0; |
| 1192 if (!subtable.ReadU16(&script_count)) { | 1202 if (!subtable.ReadU16(&script_count)) { |
| 1193 return OTS_FAILURE(); | 1203 return OTS_FAILURE_MSG("Failed to read script count in script list table"); |
| 1194 } | 1204 } |
| 1195 | 1205 |
| 1196 const unsigned script_record_end = | 1206 const unsigned script_record_end = |
| 1197 6 * static_cast<unsigned>(script_count) + 2; | 1207 6 * static_cast<unsigned>(script_count) + 2; |
| 1198 if (script_record_end > std::numeric_limits<uint16_t>::max()) { | 1208 if (script_record_end > std::numeric_limits<uint16_t>::max()) { |
| 1199 return OTS_FAILURE(); | 1209 return OTS_FAILURE_MSG("Bad end of script record %d in script list table", s
cript_record_end); |
| 1200 } | 1210 } |
| 1201 std::vector<ScriptRecord> script_list; | 1211 std::vector<ScriptRecord> script_list; |
| 1202 script_list.reserve(script_count); | 1212 script_list.reserve(script_count); |
| 1203 uint32_t last_tag = 0; | 1213 uint32_t last_tag = 0; |
| 1204 for (unsigned i = 0; i < script_count; ++i) { | 1214 for (unsigned i = 0; i < script_count; ++i) { |
| 1205 ScriptRecord record; | 1215 ScriptRecord record; |
| 1206 if (!subtable.ReadU32(&record.tag) || | 1216 if (!subtable.ReadU32(&record.tag) || |
| 1207 !subtable.ReadU16(&record.offset)) { | 1217 !subtable.ReadU16(&record.offset)) { |
| 1208 return OTS_FAILURE(); | 1218 return OTS_FAILURE_MSG("Failed to read script record %d in script list tab
le", i); |
| 1209 } | 1219 } |
| 1210 // Script tags should be arranged alphabetically by tag | 1220 // Script tags should be arranged alphabetically by tag |
| 1211 if (last_tag != 0 && last_tag > record.tag) { | 1221 if (last_tag != 0 && last_tag > record.tag) { |
| 1212 // Several fonts don't arrange tags alphabetically. | 1222 // Several fonts don't arrange tags alphabetically. |
| 1213 // It seems that the order of tags might not be a security issue | 1223 // It seems that the order of tags might not be a security issue |
| 1214 // so we just warn it. | 1224 // so we just warn it. |
| 1215 OTS_WARNING("tags aren't arranged alphabetically."); | 1225 OTS_WARNING("tags aren't arranged alphabetically."); |
| 1216 } | 1226 } |
| 1217 last_tag = record.tag; | 1227 last_tag = record.tag; |
| 1218 if (record.offset < script_record_end || record.offset >= length) { | 1228 if (record.offset < script_record_end || record.offset >= length) { |
| 1219 return OTS_FAILURE(); | 1229 return OTS_FAILURE_MSG("Bad record offset %d for script %4.4s entry %d in
script list table", record.offset, (char *)&record.tag, i); |
| 1220 } | 1230 } |
| 1221 script_list.push_back(record); | 1231 script_list.push_back(record); |
| 1222 } | 1232 } |
| 1223 if (script_list.size() != script_count) { | 1233 if (script_list.size() != script_count) { |
| 1224 return OTS_FAILURE(); | 1234 return OTS_FAILURE_MSG("Bad script list size %ld in script list table", scri
pt_list.size()); |
| 1225 } | 1235 } |
| 1226 | 1236 |
| 1227 // Check script records. | 1237 // Check script records. |
| 1228 for (unsigned i = 0; i < script_count; ++i) { | 1238 for (unsigned i = 0; i < script_count; ++i) { |
| 1229 if (!ParseScriptTable(data + script_list[i].offset, | 1239 if (!ParseScriptTable(file, data + script_list[i].offset, |
| 1230 length - script_list[i].offset, | 1240 length - script_list[i].offset, |
| 1231 script_list[i].tag, num_features)) { | 1241 script_list[i].tag, num_features)) { |
| 1232 return OTS_FAILURE(); | 1242 return OTS_FAILURE_MSG("Failed to parse script table %d", i); |
| 1233 } | 1243 } |
| 1234 } | 1244 } |
| 1235 | 1245 |
| 1236 return true; | 1246 return true; |
| 1237 } | 1247 } |
| 1238 | 1248 |
| 1239 // Parsing FeatureListTable requires number of lookups so we need to parse | 1249 // Parsing FeatureListTable requires number of lookups so we need to parse |
| 1240 // LookupListTable before calling this function. | 1250 // LookupListTable before calling this function. |
| 1241 bool ParseFeatureListTable(const uint8_t *data, const size_t length, | 1251 bool ParseFeatureListTable(const ots::OpenTypeFile *file, |
| 1252 const uint8_t *data, const size_t length, |
| 1242 const uint16_t num_lookups, | 1253 const uint16_t num_lookups, |
| 1243 uint16_t* num_features) { | 1254 uint16_t* num_features) { |
| 1244 Buffer subtable(data, length); | 1255 Buffer subtable(data, length); |
| 1245 | 1256 |
| 1246 uint16_t feature_count = 0; | 1257 uint16_t feature_count = 0; |
| 1247 if (!subtable.ReadU16(&feature_count)) { | 1258 if (!subtable.ReadU16(&feature_count)) { |
| 1248 return OTS_FAILURE(); | 1259 return OTS_FAILURE_MSG("Failed to read feature count"); |
| 1249 } | 1260 } |
| 1250 | 1261 |
| 1251 std::vector<FeatureRecord> feature_records; | 1262 std::vector<FeatureRecord> feature_records; |
| 1252 feature_records.resize(feature_count); | 1263 feature_records.resize(feature_count); |
| 1253 const unsigned feature_record_end = | 1264 const unsigned feature_record_end = |
| 1254 6 * static_cast<unsigned>(feature_count) + 2; | 1265 6 * static_cast<unsigned>(feature_count) + 2; |
| 1255 if (feature_record_end > std::numeric_limits<uint16_t>::max()) { | 1266 if (feature_record_end > std::numeric_limits<uint16_t>::max()) { |
| 1256 return OTS_FAILURE(); | 1267 return OTS_FAILURE_MSG("Bad end of feature record %d", feature_record_end); |
| 1257 } | 1268 } |
| 1258 uint32_t last_tag = 0; | 1269 uint32_t last_tag = 0; |
| 1259 for (unsigned i = 0; i < feature_count; ++i) { | 1270 for (unsigned i = 0; i < feature_count; ++i) { |
| 1260 if (!subtable.ReadU32(&feature_records[i].tag) || | 1271 if (!subtable.ReadU32(&feature_records[i].tag) || |
| 1261 !subtable.ReadU16(&feature_records[i].offset)) { | 1272 !subtable.ReadU16(&feature_records[i].offset)) { |
| 1262 return OTS_FAILURE(); | 1273 return OTS_FAILURE_MSG("Failed to read feature header %d", i); |
| 1263 } | 1274 } |
| 1264 // Feature record array should be arranged alphabetically by tag | 1275 // Feature record array should be arranged alphabetically by tag |
| 1265 if (last_tag != 0 && last_tag > feature_records[i].tag) { | 1276 if (last_tag != 0 && last_tag > feature_records[i].tag) { |
| 1266 // Several fonts don't arrange tags alphabetically. | 1277 // Several fonts don't arrange tags alphabetically. |
| 1267 // It seems that the order of tags might not be a security issue | 1278 // It seems that the order of tags might not be a security issue |
| 1268 // so we just warn it. | 1279 // so we just warn it. |
| 1269 OTS_WARNING("tags aren't arranged alphabetically."); | 1280 OTS_WARNING("tags aren't arranged alphabetically."); |
| 1270 } | 1281 } |
| 1271 last_tag = feature_records[i].tag; | 1282 last_tag = feature_records[i].tag; |
| 1272 if (feature_records[i].offset < feature_record_end || | 1283 if (feature_records[i].offset < feature_record_end || |
| 1273 feature_records[i].offset >= length) { | 1284 feature_records[i].offset >= length) { |
| 1274 return OTS_FAILURE(); | 1285 return OTS_FAILURE_MSG("Bad feature offset %d for feature %d %4.4s", featu
re_records[i].offset, i, (char *)&feature_records[i].tag); |
| 1275 } | 1286 } |
| 1276 } | 1287 } |
| 1277 | 1288 |
| 1278 for (unsigned i = 0; i < feature_count; ++i) { | 1289 for (unsigned i = 0; i < feature_count; ++i) { |
| 1279 if (!ParseFeatureTable(data + feature_records[i].offset, | 1290 if (!ParseFeatureTable(file, data + feature_records[i].offset, |
| 1280 length - feature_records[i].offset, num_lookups)) { | 1291 length - feature_records[i].offset, num_lookups)) { |
| 1281 return OTS_FAILURE(); | 1292 return OTS_FAILURE_MSG("Failed to parse feature table %d", i); |
| 1282 } | 1293 } |
| 1283 } | 1294 } |
| 1284 *num_features = feature_count; | 1295 *num_features = feature_count; |
| 1285 return true; | 1296 return true; |
| 1286 } | 1297 } |
| 1287 | 1298 |
| 1288 // For parsing GPOS/GSUB tables, this function should be called at first to | 1299 // For parsing GPOS/GSUB tables, this function should be called at first to |
| 1289 // obtain the number of lookups because parsing FeatureTableList requires | 1300 // obtain the number of lookups because parsing FeatureTableList requires |
| 1290 // the number. | 1301 // the number. |
| 1291 bool ParseLookupListTable(OpenTypeFile *file, const uint8_t *data, | 1302 bool ParseLookupListTable(OpenTypeFile *file, const uint8_t *data, |
| 1292 const size_t length, | 1303 const size_t length, |
| 1293 const LookupSubtableParser* parser, | 1304 const LookupSubtableParser* parser, |
| 1294 uint16_t *num_lookups) { | 1305 uint16_t *num_lookups) { |
| 1295 Buffer subtable(data, length); | 1306 Buffer subtable(data, length); |
| 1296 | 1307 |
| 1297 if (!subtable.ReadU16(num_lookups)) { | 1308 if (!subtable.ReadU16(num_lookups)) { |
| 1298 return OTS_FAILURE(); | 1309 return OTS_FAILURE_MSG("Failed to read number of lookups"); |
| 1299 } | 1310 } |
| 1300 | 1311 |
| 1301 std::vector<uint16_t> lookups; | 1312 std::vector<uint16_t> lookups; |
| 1302 lookups.reserve(*num_lookups); | 1313 lookups.reserve(*num_lookups); |
| 1303 const unsigned lookup_end = | 1314 const unsigned lookup_end = |
| 1304 2 * static_cast<unsigned>(*num_lookups) + 2; | 1315 2 * static_cast<unsigned>(*num_lookups) + 2; |
| 1305 if (lookup_end > std::numeric_limits<uint16_t>::max()) { | 1316 if (lookup_end > std::numeric_limits<uint16_t>::max()) { |
| 1306 return OTS_FAILURE(); | 1317 return OTS_FAILURE_MSG("Bad end of lookups %d", lookup_end); |
| 1307 } | 1318 } |
| 1308 for (unsigned i = 0; i < *num_lookups; ++i) { | 1319 for (unsigned i = 0; i < *num_lookups; ++i) { |
| 1309 uint16_t offset = 0; | 1320 uint16_t offset = 0; |
| 1310 if (!subtable.ReadU16(&offset)) { | 1321 if (!subtable.ReadU16(&offset)) { |
| 1311 return OTS_FAILURE(); | 1322 return OTS_FAILURE_MSG("Failed to read lookup offset %d", i); |
| 1312 } | 1323 } |
| 1313 if (offset < lookup_end || offset >= length) { | 1324 if (offset < lookup_end || offset >= length) { |
| 1314 return OTS_FAILURE(); | 1325 return OTS_FAILURE_MSG("Bad lookup offset %d for lookup %d", offset, i); |
| 1315 } | 1326 } |
| 1316 lookups.push_back(offset); | 1327 lookups.push_back(offset); |
| 1317 } | 1328 } |
| 1318 if (lookups.size() != *num_lookups) { | 1329 if (lookups.size() != *num_lookups) { |
| 1319 return OTS_FAILURE(); | 1330 return OTS_FAILURE_MSG("Bad lookup offsets list size %ld", lookups.size()); |
| 1320 } | 1331 } |
| 1321 | 1332 |
| 1322 for (unsigned i = 0; i < *num_lookups; ++i) { | 1333 for (unsigned i = 0; i < *num_lookups; ++i) { |
| 1323 if (!ParseLookupTable(file, data + lookups[i], length - lookups[i], | 1334 if (!ParseLookupTable(file, data + lookups[i], length - lookups[i], |
| 1324 parser)) { | 1335 parser)) { |
| 1325 return OTS_FAILURE(); | 1336 return OTS_FAILURE_MSG("Failed to parse lookup %d", i); |
| 1326 } | 1337 } |
| 1327 } | 1338 } |
| 1328 | 1339 |
| 1329 return true; | 1340 return true; |
| 1330 } | 1341 } |
| 1331 | 1342 |
| 1332 bool ParseClassDefTable(const uint8_t *data, size_t length, | 1343 bool ParseClassDefTable(const ots::OpenTypeFile *file, |
| 1344 const uint8_t *data, size_t length, |
| 1333 const uint16_t num_glyphs, | 1345 const uint16_t num_glyphs, |
| 1334 const uint16_t num_classes) { | 1346 const uint16_t num_classes) { |
| 1335 Buffer subtable(data, length); | 1347 Buffer subtable(data, length); |
| 1336 | 1348 |
| 1337 uint16_t format = 0; | 1349 uint16_t format = 0; |
| 1338 if (!subtable.ReadU16(&format)) { | 1350 if (!subtable.ReadU16(&format)) { |
| 1339 return OTS_FAILURE(); | 1351 return OTS_FAILURE_MSG("Failed to read class defn format"); |
| 1340 } | 1352 } |
| 1341 if (format == 1) { | 1353 if (format == 1) { |
| 1342 return ParseClassDefFormat1(data, length, num_glyphs, num_classes); | 1354 return ParseClassDefFormat1(file, data, length, num_glyphs, num_classes); |
| 1343 } else if (format == 2) { | 1355 } else if (format == 2) { |
| 1344 return ParseClassDefFormat2(data, length, num_glyphs, num_classes); | 1356 return ParseClassDefFormat2(file, data, length, num_glyphs, num_classes); |
| 1345 } | 1357 } |
| 1346 | 1358 |
| 1347 return OTS_FAILURE(); | 1359 return OTS_FAILURE_MSG("Bad class defn format %d", format); |
| 1348 } | 1360 } |
| 1349 | 1361 |
| 1350 bool ParseCoverageTable(const uint8_t *data, size_t length, | 1362 bool ParseCoverageTable(const ots::OpenTypeFile *file, |
| 1363 const uint8_t *data, size_t length, |
| 1351 const uint16_t num_glyphs, | 1364 const uint16_t num_glyphs, |
| 1352 const uint16_t expected_num_glyphs) { | 1365 const uint16_t expected_num_glyphs) { |
| 1353 Buffer subtable(data, length); | 1366 Buffer subtable(data, length); |
| 1354 | 1367 |
| 1355 uint16_t format = 0; | 1368 uint16_t format = 0; |
| 1356 if (!subtable.ReadU16(&format)) { | 1369 if (!subtable.ReadU16(&format)) { |
| 1357 return OTS_FAILURE(); | 1370 return OTS_FAILURE_MSG("Failed to read coverage table format"); |
| 1358 } | 1371 } |
| 1359 if (format == 1) { | 1372 if (format == 1) { |
| 1360 return ParseCoverageFormat1(data, length, num_glyphs, expected_num_glyphs); | 1373 return ParseCoverageFormat1(file, data, length, num_glyphs, expected_num_gly
phs); |
| 1361 } else if (format == 2) { | 1374 } else if (format == 2) { |
| 1362 return ParseCoverageFormat2(data, length, num_glyphs, expected_num_glyphs); | 1375 return ParseCoverageFormat2(file, data, length, num_glyphs, expected_num_gly
phs); |
| 1363 } | 1376 } |
| 1364 | 1377 |
| 1365 return OTS_FAILURE(); | 1378 return OTS_FAILURE_MSG("Bad coverage table format %d", format); |
| 1366 } | 1379 } |
| 1367 | 1380 |
| 1368 bool ParseDeviceTable(const uint8_t *data, size_t length) { | 1381 bool ParseDeviceTable(const ots::OpenTypeFile *file, |
| 1382 const uint8_t *data, size_t length) { |
| 1369 Buffer subtable(data, length); | 1383 Buffer subtable(data, length); |
| 1370 | 1384 |
| 1371 uint16_t start_size = 0; | 1385 uint16_t start_size = 0; |
| 1372 uint16_t end_size = 0; | 1386 uint16_t end_size = 0; |
| 1373 uint16_t delta_format = 0; | 1387 uint16_t delta_format = 0; |
| 1374 if (!subtable.ReadU16(&start_size) || | 1388 if (!subtable.ReadU16(&start_size) || |
| 1375 !subtable.ReadU16(&end_size) || | 1389 !subtable.ReadU16(&end_size) || |
| 1376 !subtable.ReadU16(&delta_format)) { | 1390 !subtable.ReadU16(&delta_format)) { |
| 1377 return OTS_FAILURE(); | 1391 return OTS_FAILURE_MSG("Failed to read device table header"); |
| 1378 } | 1392 } |
| 1379 if (start_size > end_size) { | 1393 if (start_size > end_size) { |
| 1380 OTS_WARNING("bad size range: %u > %u", start_size, end_size); | 1394 return OTS_FAILURE_MSG("bad size range: %u > %u", start_size, end_size); |
| 1381 return OTS_FAILURE(); | |
| 1382 } | 1395 } |
| 1383 if (delta_format == 0 || delta_format > kMaxDeltaFormatType) { | 1396 if (delta_format == 0 || delta_format > kMaxDeltaFormatType) { |
| 1384 OTS_WARNING("bad delta format: %u", delta_format); | 1397 return OTS_FAILURE_MSG("bad delta format: %u", delta_format); |
| 1385 return OTS_FAILURE(); | |
| 1386 } | 1398 } |
| 1387 // The number of delta values per uint16. The device table should contain | 1399 // The number of delta values per uint16. The device table should contain |
| 1388 // at least |num_units| * 2 bytes compressed data. | 1400 // at least |num_units| * 2 bytes compressed data. |
| 1389 const unsigned num_units = (end_size - start_size) / | 1401 const unsigned num_units = (end_size - start_size) / |
| 1390 (1 << (4 - delta_format)) + 1; | 1402 (1 << (4 - delta_format)) + 1; |
| 1391 // Just skip |num_units| * 2 bytes since the compressed data could take | 1403 // Just skip |num_units| * 2 bytes since the compressed data could take |
| 1392 // arbitrary values. | 1404 // arbitrary values. |
| 1393 if (!subtable.Skip(num_units * 2)) { | 1405 if (!subtable.Skip(num_units * 2)) { |
| 1394 return OTS_FAILURE(); | 1406 return OTS_FAILURE_MSG("Failed to skip data in device table"); |
| 1395 } | 1407 } |
| 1396 return true; | 1408 return true; |
| 1397 } | 1409 } |
| 1398 | 1410 |
| 1399 bool ParseContextSubtable(const uint8_t *data, const size_t length, | 1411 bool ParseContextSubtable(const ots::OpenTypeFile *file, |
| 1412 const uint8_t *data, const size_t length, |
| 1400 const uint16_t num_glyphs, | 1413 const uint16_t num_glyphs, |
| 1401 const uint16_t num_lookups) { | 1414 const uint16_t num_lookups) { |
| 1402 Buffer subtable(data, length); | 1415 Buffer subtable(data, length); |
| 1403 | 1416 |
| 1404 uint16_t format = 0; | 1417 uint16_t format = 0; |
| 1405 if (!subtable.ReadU16(&format)) { | 1418 if (!subtable.ReadU16(&format)) { |
| 1406 return OTS_FAILURE(); | 1419 return OTS_FAILURE_MSG("Failed to read context subtable format"); |
| 1407 } | 1420 } |
| 1408 | 1421 |
| 1409 if (format == 1) { | 1422 if (format == 1) { |
| 1410 if (!ParseContextFormat1(data, length, num_glyphs, num_lookups)) { | 1423 if (!ParseContextFormat1(file, data, length, num_glyphs, num_lookups)) { |
| 1411 return OTS_FAILURE(); | 1424 return OTS_FAILURE_MSG("Failed to parse context format 1 subtable"); |
| 1412 } | 1425 } |
| 1413 } else if (format == 2) { | 1426 } else if (format == 2) { |
| 1414 if (!ParseContextFormat2(data, length, num_glyphs, num_lookups)) { | 1427 if (!ParseContextFormat2(file, data, length, num_glyphs, num_lookups)) { |
| 1415 return OTS_FAILURE(); | 1428 return OTS_FAILURE_MSG("Failed to parse context format 2 subtable"); |
| 1416 } | 1429 } |
| 1417 } else if (format == 3) { | 1430 } else if (format == 3) { |
| 1418 if (!ParseContextFormat3(data, length, num_glyphs, num_lookups)) { | 1431 if (!ParseContextFormat3(file, data, length, num_glyphs, num_lookups)) { |
| 1419 return OTS_FAILURE(); | 1432 return OTS_FAILURE_MSG("Failed to parse context format 3 subtable"); |
| 1420 } | 1433 } |
| 1421 } else { | 1434 } else { |
| 1422 return OTS_FAILURE(); | 1435 return OTS_FAILURE_MSG("Bad context subtable format %d", format); |
| 1423 } | 1436 } |
| 1424 | 1437 |
| 1425 return true; | 1438 return true; |
| 1426 } | 1439 } |
| 1427 | 1440 |
| 1428 bool ParseChainingContextSubtable(const uint8_t *data, const size_t length, | 1441 bool ParseChainingContextSubtable(const ots::OpenTypeFile *file, |
| 1442 const uint8_t *data, const size_t length, |
| 1429 const uint16_t num_glyphs, | 1443 const uint16_t num_glyphs, |
| 1430 const uint16_t num_lookups) { | 1444 const uint16_t num_lookups) { |
| 1431 Buffer subtable(data, length); | 1445 Buffer subtable(data, length); |
| 1432 | 1446 |
| 1433 uint16_t format = 0; | 1447 uint16_t format = 0; |
| 1434 if (!subtable.ReadU16(&format)) { | 1448 if (!subtable.ReadU16(&format)) { |
| 1435 return OTS_FAILURE(); | 1449 return OTS_FAILURE_MSG("Failed to read chaining context subtable format"); |
| 1436 } | 1450 } |
| 1437 | 1451 |
| 1438 if (format == 1) { | 1452 if (format == 1) { |
| 1439 if (!ParseChainContextFormat1(data, length, num_glyphs, num_lookups)) { | 1453 if (!ParseChainContextFormat1(file, data, length, num_glyphs, num_lookups))
{ |
| 1440 return OTS_FAILURE(); | 1454 return OTS_FAILURE_MSG("Failed to parse chaining context format 1 subtable
"); |
| 1441 } | 1455 } |
| 1442 } else if (format == 2) { | 1456 } else if (format == 2) { |
| 1443 if (!ParseChainContextFormat2(data, length, num_glyphs, num_lookups)) { | 1457 if (!ParseChainContextFormat2(file, data, length, num_glyphs, num_lookups))
{ |
| 1444 return OTS_FAILURE(); | 1458 return OTS_FAILURE_MSG("Failed to parse chaining context format 2 subtable
"); |
| 1445 } | 1459 } |
| 1446 } else if (format == 3) { | 1460 } else if (format == 3) { |
| 1447 if (!ParseChainContextFormat3(data, length, num_glyphs, num_lookups)) { | 1461 if (!ParseChainContextFormat3(file, data, length, num_glyphs, num_lookups))
{ |
| 1448 return OTS_FAILURE(); | 1462 return OTS_FAILURE_MSG("Failed to parse chaining context format 3 subtable
"); |
| 1449 } | 1463 } |
| 1450 } else { | 1464 } else { |
| 1451 return OTS_FAILURE(); | 1465 return OTS_FAILURE_MSG("Bad chaining context subtable format %d", format); |
| 1452 } | 1466 } |
| 1453 | 1467 |
| 1454 return true; | 1468 return true; |
| 1455 } | 1469 } |
| 1456 | 1470 |
| 1457 bool ParseExtensionSubtable(const OpenTypeFile *file, | 1471 bool ParseExtensionSubtable(const OpenTypeFile *file, |
| 1458 const uint8_t *data, const size_t length, | 1472 const uint8_t *data, const size_t length, |
| 1459 const LookupSubtableParser* parser) { | 1473 const LookupSubtableParser* parser) { |
| 1460 Buffer subtable(data, length); | 1474 Buffer subtable(data, length); |
| 1461 | 1475 |
| 1462 uint16_t format = 0; | 1476 uint16_t format = 0; |
| 1463 uint16_t lookup_type = 0; | 1477 uint16_t lookup_type = 0; |
| 1464 uint32_t offset_extension = 0; | 1478 uint32_t offset_extension = 0; |
| 1465 if (!subtable.ReadU16(&format) || | 1479 if (!subtable.ReadU16(&format) || |
| 1466 !subtable.ReadU16(&lookup_type) || | 1480 !subtable.ReadU16(&lookup_type) || |
| 1467 !subtable.ReadU32(&offset_extension)) { | 1481 !subtable.ReadU32(&offset_extension)) { |
| 1468 return OTS_FAILURE(); | 1482 return OTS_FAILURE_MSG("Failed to read extension table header"); |
| 1469 } | 1483 } |
| 1470 | 1484 |
| 1471 if (format != 1) { | 1485 if (format != 1) { |
| 1472 return OTS_FAILURE(); | 1486 return OTS_FAILURE_MSG("Bad extension table format %d", format); |
| 1473 } | 1487 } |
| 1474 // |lookup_type| should be other than |parser->extension_type|. | 1488 // |lookup_type| should be other than |parser->extension_type|. |
| 1475 if (lookup_type < 1 || lookup_type > parser->num_types || | 1489 if (lookup_type < 1 || lookup_type > parser->num_types || |
| 1476 lookup_type == parser->extension_type) { | 1490 lookup_type == parser->extension_type) { |
| 1477 return OTS_FAILURE(); | 1491 return OTS_FAILURE_MSG("Bad lookup type %d in extension table", lookup_type)
; |
| 1478 } | 1492 } |
| 1479 | 1493 |
| 1480 const unsigned format_end = static_cast<unsigned>(8); | 1494 const unsigned format_end = static_cast<unsigned>(8); |
| 1481 if (offset_extension < format_end || | 1495 if (offset_extension < format_end || |
| 1482 offset_extension >= length) { | 1496 offset_extension >= length) { |
| 1483 return OTS_FAILURE(); | 1497 return OTS_FAILURE_MSG("Bad extension offset %d", offset_extension); |
| 1484 } | 1498 } |
| 1485 | 1499 |
| 1486 // Parse the extension subtable of |lookup_type|. | 1500 // Parse the extension subtable of |lookup_type|. |
| 1487 if (!parser->Parse(file, data + offset_extension, length - offset_extension, | 1501 if (!parser->Parse(file, data + offset_extension, length - offset_extension, |
| 1488 lookup_type)) { | 1502 lookup_type)) { |
| 1489 return OTS_FAILURE(); | 1503 return OTS_FAILURE_MSG("Failed to parse lookup from extension lookup"); |
| 1490 } | 1504 } |
| 1491 | 1505 |
| 1492 return true; | 1506 return true; |
| 1493 } | 1507 } |
| 1494 | 1508 |
| 1495 } // namespace ots | 1509 } // namespace ots |
| 1496 | 1510 |
| 1511 #undef TABLE_NAME |
| OLD | NEW |